null+****@clear*****
null+****@clear*****
2012年 2月 3日 (金) 21:20:23 JST
Kouhei Sutou 2012-01-17 12:10:35 +0900 (Tue, 17 Jan 2012) New Revision: 7ed55f166628764e3087745c8ccf0c4cd15b9f26 Log: remove deprecated grn_query. fixes #1247 Added files: lib/ctx_impl.h Removed files: lib/ql.c lib/ql.h lib/query.c lib/scm.c test/unit/core/test-query.c Modified files: include/groonga.h lib/Makefile.am lib/com.c lib/ctx.c lib/db.c lib/expr.c lib/ii.c lib/ii.h lib/io.c lib/output.c lib/output.h lib/plugin.c lib/proc.c lib/store.c lib/token.c src/grnslap.c src/groonga.c test/unit/core/Makefile.am test/unit/core/test-inverted-index.c Modified: include/groonga.h (+0 -16) =================================================================== --- include/groonga.h 2012-02-03 11:43:41 +0900 (101af22) +++ include/groonga.h 2012-01-17 12:10:35 +0900 (8a078c2) @@ -1965,31 +1965,15 @@ GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor); #endif /* GRN_QUERY_COLUMN */ typedef struct _grn_snip grn_snip; -typedef struct _grn_query grn_query; typedef struct _grn_snip_mapping grn_snip_mapping; struct _grn_snip_mapping { void *dummy; }; -GRN_API grn_query *grn_query_open(grn_ctx *ctx, const char *str, unsigned int str_len, - grn_operator default_op, int max_exprs); -GRN_API unsigned int grn_query_rest(grn_ctx *ctx, grn_query *q, const char ** const rest); -GRN_API grn_rc grn_query_close(grn_ctx *ctx, grn_query *q); - -GRN_API grn_rc grn_query_scan(grn_ctx *ctx, grn_query *q, const char **strs, unsigned int *str_lens, - unsigned int nstrs, int flags, int *found, int *score); -GRN_API grn_snip *grn_query_snip(grn_ctx *ctx, grn_query *query, int flags, - unsigned int width, unsigned int max_results, - unsigned int n_tags, - const char **opentags, unsigned int *opentag_lens, - const char **closetags, unsigned int *closetag_lens, - grn_snip_mapping *mapping); - #define GRN_SNIP_NORMALIZE (0x01<<0) #define GRN_SNIP_COPY_TAG (0x01<<1) #define GRN_SNIP_SKIP_LEADING_SPACES (0x01<<2) -#define GRN_QUERY_SCAN_NORMALIZE GRN_SNIP_NORMALIZE GRN_API grn_snip *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width, unsigned int max_results, Modified: lib/Makefile.am (+2 -5) =================================================================== --- lib/Makefile.am 2012-02-03 11:43:41 +0900 (a453309) +++ lib/Makefile.am 2012-01-17 12:10:35 +0900 (07f0b84) @@ -12,11 +12,8 @@ libgroonga_la_SOURCES = \ str.c \ nfkc.c \ snip.c \ - query.c \ store.c \ com.c \ - ql.c \ - scm.c \ ctx.c \ hash.c \ db.c \ @@ -39,9 +36,10 @@ libgroonga_la_LDFLAGS = \ libgroonga_la_LIBADD = \ dat/libgrndat.la -noinst_HEADERS = \ +noinst_HEADERS = \ com.h \ ctx.h \ + ctx_impl.h \ dat.h \ db.h \ geo.h \ @@ -54,7 +52,6 @@ noinst_HEADERS = \ pat.h \ plugin_in.h \ proc.h \ - ql.h \ snip.h \ store.h \ str.h \ Modified: lib/com.c (+2 -2) =================================================================== --- lib/com.c 2012-02-03 11:43:41 +0900 (5fc9f48) +++ lib/com.c 2012-01-17 12:10:35 +0900 (da028ec) @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2011 Brazil +/* Copyright(C) 2009-2012 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,7 +19,7 @@ #include <stdio.h> #include <string.h> -#include "ql.h" +#include "ctx_impl.h" #ifdef WIN32 # include <ws2tcpip.h> Modified: lib/ctx.c (+19 -202) =================================================================== --- lib/ctx.c 2012-02-03 11:43:41 +0900 (6cbf03d) +++ lib/ctx.c 2012-01-17 12:10:35 +0900 (69d9a0e) @@ -19,7 +19,7 @@ #include "groonga_in.h" #include <string.h> #include "token.h" -#include "ql.h" +#include "ctx_impl.h" #include "pat.h" #include "plugin_in.h" #include "snip.h" @@ -420,12 +420,20 @@ grn_ctx_impl_init(grn_ctx *ctx) ctx->impl->encoding = ctx->encoding; ctx->impl->lifoseg = -1; ctx->impl->currseg = -1; - if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_tmp_db_obj), + if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_db_obj *), GRN_ARRAY_TINY))) { grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); ctx->impl = NULL; return; } + if (!(ctx->impl->ios = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_io *), + GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) { + grn_array_close(ctx, ctx->impl->values); + grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); + ctx->impl = NULL; + return; + } CRITICAL_SECTION_INIT(ctx->impl->lock); ctx->impl->db = NULL; @@ -454,29 +462,12 @@ grn_ctx_impl_init(grn_ctx *ctx) ctx->impl->finalizer = NULL; - ctx->impl->phs = NIL; - ctx->impl->code = NIL; - ctx->impl->dump = NIL; ctx->impl->op = GRN_OP_T0LVL; - ctx->impl->args = NIL; - ctx->impl->envir = NIL; - ctx->impl->value = NIL; - ctx->impl->ncells = 0; ctx->impl->n_entries = 0; - ctx->impl->seqno = 0; - ctx->impl->lseqno = 0; - ctx->impl->nbinds = 0; - ctx->impl->nunbinds = 0; - ctx->impl->feed_mode = grn_ql_atonce; ctx->impl->cur = NULL; ctx->impl->str_end = NULL; ctx->impl->batchmode = 0; - ctx->impl->gc_verbose = 0; ctx->impl->inbuf = NULL; - ctx->impl->co.mode = 0; - ctx->impl->co.func = NULL; - ctx->impl->objects = NULL; - ctx->impl->symbols = NULL; ctx->impl->com = NULL; ctx->impl->outbuf = grn_obj_open(ctx, GRN_BULK, 0, 0); ctx->impl->output = NULL /* grn_ctx_concat_func */; @@ -508,37 +499,6 @@ grn_ctx_impl_err(grn_ctx *ctx) } } -static void -grn_ctx_ql_init(grn_ctx *ctx, int flags) -{ - if (!ctx->impl) { - grn_ctx_impl_init(ctx); - if (ERRP(ctx, GRN_ERROR)) { return; } - } - if (flags & GRN_CTX_BATCH_MODE) { ctx->impl->batchmode = 1; } - if ((ctx->impl->objects = grn_array_create(ctx, NULL, sizeof(grn_cell), - GRN_ARRAY_TINY))) { - if ((ctx->impl->symbols = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, - sizeof(grn_cell), - GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) { - if (!ERRP(ctx, GRN_ERROR)) { - grn_ql_init_globals(ctx); - if (!ERRP(ctx, GRN_ERROR)) { - return; - } - } - grn_hash_close(ctx, ctx->impl->symbols); - ctx->impl->symbols = NULL; - } else { - MERR("ctx->impl->symbols init failed"); - } - grn_array_close(ctx, ctx->impl->objects); - ctx->impl->objects = NULL; - } else { - MERR("ctx->impl->objects init failed"); - } -} - grn_rc grn_ctx_init(grn_ctx *ctx, int flags) { @@ -549,15 +509,14 @@ grn_ctx_init(grn_ctx *ctx, int flags) if (getenv("GRN_CTX_PER_DB") && strcmp(getenv("GRN_CTX_PER_DB"), "yes") == 0) { ctx->flags |= GRN_CTX_PER_DB; } - ctx->stat = GRN_QL_WAIT_EXPR; + if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; } + ctx->stat = GRN_CTX_INITED; ctx->encoding = grn_gctx.encoding; - ctx->seqno = 0; - ctx->seqno2 = 0; - ctx->subno = 0; ctx->impl = NULL; if (flags & GRN_CTX_USE_QL) { - grn_ctx_ql_init(ctx, flags); + grn_ctx_impl_init(ctx); if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; } + if (flags & GRN_CTX_BATCH_MODE) { ctx->impl->batchmode = 1; } } ctx->user_data.ptr = NULL; CRITICAL_SECTION_ENTER(grn_glock); @@ -606,25 +565,18 @@ grn_ctx_fin(grn_ctx *ctx) ctx->impl->finalizer(ctx, 0, NULL, &(ctx->user_data)); } grn_ctx_loader_clear(ctx); - if (ctx->impl->objects) { - grn_cell *o; - GRN_ARRAY_EACH(ctx, ctx->impl->objects, 0, 0, id, &o, { - grn_cell_clear(ctx, o); - }); - grn_array_close(ctx, ctx->impl->objects); - } if (ctx->impl->parser) { grn_expr_parser_close(ctx); } if (ctx->impl->values) { - grn_tmp_db_obj *o; + grn_db_obj *o; GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { - grn_obj_close(ctx, (grn_obj *)o->obj); + grn_obj_close(ctx, *((grn_obj **)o)); }); grn_array_close(ctx, ctx->impl->values); } - if (ctx->impl->symbols) { - grn_hash_close(ctx, ctx->impl->symbols); + if (ctx->impl->ios) { + grn_hash_close(ctx, ctx->impl->ios); } if (ctx->impl->com) { if (ctx->stat != GRN_CTX_QUIT) { @@ -795,7 +747,6 @@ grn_init(void) CRITICAL_SECTION_INIT(grn_glock); CRITICAL_SECTION_INIT(grn_logger_lock); grn_gtick = 0; - grn_ql_init_const(); ctx->next = ctx; ctx->prev = ctx; grn_ctx_init(ctx, 0); @@ -862,11 +813,7 @@ grn_init(void) GRN_LOG(ctx, GRN_LOG_ALERT, "grn_com_init failed (%d)", rc); return rc; } - grn_ctx_ql_init(ctx, 0); - if ((rc = ctx->rc)) { - GRN_LOG(ctx, GRN_LOG_ALERT, "gctx initialize failed (%d)", rc); - return rc; - } + grn_ctx_impl_init(ctx); if ((rc = grn_io_init())) { GRN_LOG(ctx, GRN_LOG_ALERT, "io initialize failed (%d)", rc); return rc; @@ -1527,45 +1474,6 @@ grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info) } -grn_cell * -grn_get(const char *key) -{ - grn_cell *obj; - if (!grn_gctx.impl || !grn_gctx.impl->symbols || - !grn_hash_add(&grn_gctx, grn_gctx.impl->symbols, key, strlen(key), - (void **) &obj, NULL)) { - GRN_LOG(&grn_gctx, GRN_LOG_WARNING, "grn_get(%s) failed", key); - return F; - } - if (!obj->header.impl_flags) { - obj->header.impl_flags |= GRN_CELL_SYMBOL; - obj->header.type = GRN_VOID; - } - return obj; -} - -grn_cell * -grn_at(const char *key) -{ - grn_cell *obj; - if (!grn_gctx.impl || grn_gctx.impl->symbols || - !grn_hash_get(&grn_gctx, grn_gctx.impl->symbols, - key, strlen(key), (void **) &obj)) { - return F; - } - return obj; -} - -grn_rc -grn_del(const char *key) -{ - if (!grn_gctx.impl || !grn_gctx.impl->symbols) { - GRN_LOG(&grn_gctx, GRN_LOG_WARNING, "grn_del(%s) failed", key); - return GRN_INVALID_ARGUMENT; - } - return grn_hash_delete(&grn_gctx, grn_gctx.impl->symbols, key, strlen(key), NULL); -} - typedef struct _grn_cache_entry grn_cache_entry; typedef struct { @@ -2323,97 +2231,6 @@ grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const c } #endif /* USE_FAIL_MALLOC */ -grn_cell * -grn_cell_new(grn_ctx *ctx) -{ - grn_cell *o = NULL; - if (ctx && ctx->impl) { - grn_array_add(ctx, ctx->impl->objects, (void **)&o); - if (o) { - o->header.impl_flags = 0; - ctx->impl->n_entries++; - } - } - return o; -} - -grn_cell * -grn_cell_cons(grn_ctx *ctx, grn_cell *a, grn_cell *b) -{ - if (!ctx) { return NULL; } - { - grn_cell *o; - GRN_CELL_NEW(ctx, o); - if (o) { - o->header.type = GRN_CELL_LIST; - o->header.impl_flags = 0; - o->u.l.car = a; - o->u.l.cdr = b; - } - return o; - } -} - -grn_cell * -grn_cell_alloc(grn_ctx *ctx, uint32_t size) -{ - if (!ctx) { return NULL; } - { - void *value = GRN_MALLOC(size + 1); - if (value) { - grn_cell *o = grn_cell_new(ctx); - if (!ERRP(ctx, GRN_ERROR)) { - o->header.impl_flags = GRN_OBJ_ALLOCATED; - o->header.type = GRN_CELL_STR; - o->u.b.size = size; - o->u.b.value = value; - return o; - } - GRN_FREE(value); - } else { - MERR("malloc(%d) failed", size + 1); - } - return NULL; - } -} - -void -grn_cell_clear(grn_ctx *ctx, grn_cell *o) -{ - if (!ctx || !ctx->impl) { return; } - if (o->header.impl_flags & GRN_OBJ_ALLOCATED) { - switch (o->header.type) { - case GRN_SNIP : - if (o->u.p.value) { grn_snip_close(ctx, (grn_snip *)o->u.p.value); } - break; - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_NO_KEY : - grn_obj_close(ctx, grn_ctx_at(ctx, o->u.o.id)); - break; - case GRN_CELL_STR : - if (o->u.b.value) { - GRN_FREE(o->u.b.value); - } - break; - case GRN_QUERY : - if (o->u.p.value) { grn_query_close(ctx, (grn_query *)o->u.p.value); } - break; - case GRN_UVECTOR : - case GRN_VECTOR : - if (o->u.p.value) { grn_obj_close(ctx, o->u.p.value); } - break; - case GRN_PATSNIP : - grn_obj_patsnip_spec_close(ctx, (patsnip_spec *)o->u.p.value); - break; - default : - GRN_LOG(ctx, GRN_LOG_WARNING, "obj_clear: invalid type(%x)", o->header.type); - break; - } - o->header.impl_flags &= ~GRN_OBJ_ALLOCATED; - } -} - /* don't handle error inside logger functions */ void Added: lib/ctx_impl.h (+177 -0) 100644 =================================================================== --- /dev/null +++ lib/ctx_impl.h 2012-01-17 12:10:35 +0900 (49ae27a) @@ -0,0 +1,177 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2012 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef GRN_CTX_IMPL_H +#define GRN_CTX_IMPL_H + +#ifndef GRN_CTX_H +#include "ctx.h" +#endif /* GRN_CTX_H */ + +#ifndef GRN_COM_H +#include "com.h" +#endif /* GRN_COM_H */ + +#ifdef HAVE_MESSAGE_PACK +#include <msgpack.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/**** grn_expr ****/ + +#define GRN_EXPR_MISSING_NAME "expr_missing" + +/**** grn_ctx_impl ****/ + +#define GRN_CTX_INITED 0x00 +#define GRN_CTX_QUITTING 0x0f + +typedef enum { + GRN_LOADER_BEGIN = 0, + GRN_LOADER_TOKEN, + GRN_LOADER_STRING, + GRN_LOADER_SYMBOL, + GRN_LOADER_NUMBER, + GRN_LOADER_STRING_ESC, + GRN_LOADER_UNICODE0, + GRN_LOADER_UNICODE1, + GRN_LOADER_UNICODE2, + GRN_LOADER_UNICODE3, + GRN_LOADER_END +} grn_loader_stat; + +typedef struct { + grn_obj values; + grn_obj level; + grn_obj columns; + int32_t key_offset; + grn_obj *table; + grn_obj *last; + grn_obj *ifexists; + grn_obj *each; + uint32_t unichar; + uint32_t values_size; + uint32_t nrecords; + grn_loader_stat stat; + grn_content_type input_type; +} grn_loader; + +#define GRN_STACK_SIZE 1024 +#define GRN_CTX_N_SEGMENTS 512 + +#ifdef ENABLE_MEMORY_DEBUG +typedef struct _grn_alloc_info grn_alloc_info; +struct _grn_alloc_info +{ + void *address; + int freed; + char alloc_backtrace[4096]; + char free_backtrace[4096]; + grn_alloc_info *next; +}; +#endif + +struct _grn_ctx_impl { + grn_encoding encoding; + + /* memory pool portion */ + int32_t lifoseg; + int32_t currseg; + grn_critical_section lock; + grn_io_mapinfo segs[GRN_CTX_N_SEGMENTS]; + +#ifdef USE_DYNAMIC_MALLOC_CHANGE + /* memory allocation portion */ + grn_malloc_func malloc_func; + grn_calloc_func calloc_func; + grn_realloc_func realloc_func; + grn_strdup_func strdup_func; +#endif + +#ifdef ENABLE_MEMORY_DEBUG + /* memory debug portion */ + grn_alloc_info *alloc_info; +#endif + + /* qe portion */ + grn_obj *stack[GRN_STACK_SIZE]; + uint32_t stack_curr; + grn_hash *expr_vars; + grn_obj *curr_expr; + grn_obj *qe_next; + void *parser; + grn_timeval tv; + + /* loader portion */ + grn_edge *edge; + grn_loader loader; + + /* plugin portion */ + const char *plugin_path; + + /* output portion */ + grn_content_type output_type; + const char *mime_type; + grn_obj names; + grn_obj levels; + + /* command portion */ + grn_command_version command_version; + + /* match escalation portion */ + int64_t match_escalation_threshold; + + /* lifetime portion */ + grn_proc_func *finalizer; + + /* ql portion */ + uint8_t batchmode; + uint8_t op; + int tok; + char *cur; + char *str_end; + grn_obj *db; + uint32_t n_entries; + grn_array *values; /* temporary objects */ + grn_hash *ios; /* IOs */ + char *inbuf; + grn_obj *outbuf; + grn_obj subbuf; + unsigned int bufcur; + void (*output)(grn_ctx *, int, void *); + grn_com *com; + unsigned int com_status; + union { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; + } data; + +#ifdef HAVE_MESSAGE_PACK + msgpack_packer msgpacker; +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_CTX_IMPL_H */ Modified: lib/db.c (+9 -14) =================================================================== --- lib/db.c 2012-02-03 11:43:41 +0900 (d534ca9) +++ lib/db.c 2012-01-17 12:10:35 +0900 (9b64a10) @@ -20,7 +20,7 @@ #include "pat.h" #include "dat.h" #include "ii.h" -#include "ql.h" +#include "ctx_impl.h" #include "token.h" #include "proc.h" #include "plugin_in.h" @@ -264,9 +264,9 @@ grn_db_close(grn_ctx *ctx, grn_obj *db) grn_expr_parser_close(ctx); } if (ctx->impl->values) { - grn_tmp_db_obj *o; + grn_db_obj *o; GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { - grn_obj_close(ctx, (grn_obj *)o->obj); + grn_obj_close(ctx, *((grn_obj **)o)); }); grn_array_truncate(ctx, ctx->impl->values); } @@ -2813,7 +2813,7 @@ grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, } break; case GRN_QUERY : - rc = grn_query_search(ctx, (grn_ii *)obj, (grn_query *)query, (grn_hash *)res, op); + rc = GRN_FUNCTION_NOT_IMPLEMENTED; break; } } @@ -6594,11 +6594,8 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj) if (id) { if (id & GRN_OBJ_TMP_OBJECT) { if (ctx->impl && ctx->impl->values) { - grn_tmp_db_obj tmp_obj; - tmp_obj.obj = obj; - memset(&tmp_obj.cell, 0, sizeof(grn_cell)); rc = grn_array_set_value(ctx, ctx->impl->values, - id & ~GRN_OBJ_TMP_OBJECT, &tmp_obj, GRN_OBJ_SET); + id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET); } } else { db_value *vp; @@ -6665,9 +6662,10 @@ grn_ctx_at(grn_ctx *ctx, grn_id id) GRN_API_ENTER; if (id & GRN_OBJ_TMP_OBJECT) { if (ctx->impl->values) { - grn_tmp_db_obj *tmp_obj; - if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT))) { - res = (grn_obj *)tmp_obj->obj; + grn_obj **tmp_obj; + tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT); + if (tmp_obj) { + res = *tmp_obj; } } } else { @@ -6929,9 +6927,6 @@ grn_obj_close(grn_ctx *ctx, grn_obj *obj) case GRN_TABLE_VIEW : rc = grn_view_close(ctx, (grn_view *)obj); break; - case GRN_QUERY : - rc = grn_query_close(ctx, (grn_query *)obj); - break; case GRN_COLUMN_VAR_SIZE : rc = grn_ja_close(ctx, (grn_ja *)obj); break; Modified: lib/expr.c (+1 -1) =================================================================== --- lib/expr.c 2012-02-03 11:43:41 +0900 (6b7483b) +++ lib/expr.c 2012-01-17 12:10:35 +0900 (3c79202) @@ -17,7 +17,7 @@ */ #include "groonga_in.h" #include "db.h" -#include "ql.h" +#include "ctx_impl.h" #include <string.h> #include <float.h> #include "ii.h" Modified: lib/ii.c (+1 -2) =================================================================== --- lib/ii.c 2012-02-03 11:43:41 +0900 (3c9ca17) +++ lib/ii.c 2012-01-17 12:10:35 +0900 (4494aee) @@ -21,7 +21,7 @@ #include <sys/stat.h> #include "ii.h" -#include "ql.h" +#include "ctx_impl.h" #include "token.h" #include "pat.h" #include "db.h" @@ -3566,7 +3566,6 @@ grn_ii_close(grn_ctx *ctx, grn_ii *ii) { grn_rc rc; if (!ii) { return GRN_INVALID_ARGUMENT; } - grn_del(grn_io_path(ii->seg)); if ((rc = grn_io_close(ctx, ii->seg))) { return rc; } if ((rc = grn_io_close(ctx, ii->chunk))) { return rc; } GRN_GFREE(ii); Modified: lib/ii.h (+0 -5) =================================================================== --- lib/ii.h 2012-02-03 11:43:41 +0900 (5243446) +++ lib/ii.h 2012-01-17 12:10:35 +0900 (af289d3) @@ -180,11 +180,6 @@ GRN_API grn_rc grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsig grn_rc grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, grn_hash *s, grn_operator op, grn_search_optarg *optarg); -grn_rc grn_ii_query_select(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_hash *r, grn_operator op); - -grn_rc grn_query_search(grn_ctx *ctx, grn_ii *i, grn_query *q, - grn_hash *r, grn_operator op); - void grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op); grn_rc grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op); Modified: lib/io.c (+19 -8) =================================================================== --- lib/io.c 2012-02-03 11:43:41 +0900 (84c1009) +++ lib/io.c 2012-01-17 12:10:35 +0900 (dcb0026) @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009 Brazil +/* Copyright(C) 2009-2012 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ #include "io.h" #include "plugin_in.h" #include "hash.h" -#include "ql.h" +#include "ctx_impl.h" #define GRN_IO_IDSTR "GROONGA:IO:00001" @@ -147,8 +147,13 @@ static void grn_io_register(grn_io *io) { if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { - grn_cell *obj = grn_get(io->path); - if (obj != F) { obj->u.p.value = (grn_obj *)io; } + if (grn_gctx.impl && grn_gctx.impl->ios && + grn_hash_add(&grn_gctx, grn_gctx.impl->ios, io->path, strlen(io->path), + (void **)&io, NULL)) { + } else { + GRN_LOG(&grn_gctx, GRN_LOG_WARNING, + "grn_io_register(%s) failed", io->path); + } } } @@ -156,7 +161,13 @@ static void grn_io_unregister(grn_io *io) { if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { - grn_del(io->path); + if (grn_gctx.impl && grn_gctx.impl->ios) { + grn_hash_delete(&grn_gctx, grn_gctx.impl->ios, + io->path, strlen(io->path), NULL); + } else { + GRN_LOG(&grn_gctx, GRN_LOG_WARNING, + "grn_io_unregister(%s) failed", io->path); + } } } @@ -1388,10 +1399,10 @@ static uint32_t grn_expire_(grn_ctx *ctx, int count_thresh, uint32_t limit) { uint32_t n = 0; - grn_cell *obj; - GRN_HASH_EACH(ctx, grn_gctx.impl->symbols, id, NULL, NULL, (void **) &obj, { + grn_io *io; + GRN_HASH_EACH(ctx, grn_gctx.impl->ios, id, NULL, NULL, (void **)&io, { grn_plugin_close(ctx, id); - n += grn_io_expire(ctx, (grn_io *) obj->u.p.value, count_thresh, limit); + n += grn_io_expire(ctx, io, count_thresh, limit); if (n >= limit) { break; } }); return n; Modified: lib/output.c (+1 -2) =================================================================== --- lib/output.c 2012-02-03 11:43:41 +0900 (5c5387f) +++ lib/output.c 2012-01-17 12:10:35 +0900 (35a67c6) @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2010 Brazil +/* Copyright(C) 2009-2012 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,6 @@ #include <string.h> #include "str.h" -#include "ql.h" #include "db.h" #include "output.h" Modified: lib/output.h (+4 -4) =================================================================== --- lib/output.h 2012-02-03 11:43:41 +0900 (36c5aa7) +++ lib/output.h 2012-01-17 12:10:35 +0900 (fe91863) @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2010 Brazil +/* Copyright(C) 2010-2012 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -29,9 +29,9 @@ #include "store.h" #endif /* GRN_STORE_H */ -#ifndef GRN_QL_H -#include "ql.h" -#endif /* GRN_QL_H */ +#ifndef GRN_CTX_IMPL_H +#include "ctx_impl.h" +#endif /* GRN_CTX_IMPL_H */ #ifdef __cplusplus extern "C" { Modified: lib/plugin.c (+2 -2) =================================================================== --- lib/plugin.c 2012-02-03 11:43:41 +0900 (48e172f) +++ lib/plugin.c 2012-01-17 12:10:35 +0900 (2c03f93) @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2011 Brazil +/* Copyright(C) 2009-2012 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,7 +17,7 @@ #include "db.h" #include "plugin_in.h" -#include "ql.h" +#include "ctx_impl.h" #include "util.h" #include <stdio.h> Modified: lib/proc.c (+0 -1) =================================================================== --- lib/proc.c 2012-02-03 11:43:41 +0900 (b896eb9) +++ lib/proc.c 2012-01-17 12:10:35 +0900 (613f1f8) @@ -17,7 +17,6 @@ */ #include "proc.h" -#include "ql.h" #include "ii.h" #include "db.h" #include "util.h" Deleted: lib/ql.c (+0 -2763) 100644 =================================================================== --- lib/ql.c 2012-02-03 11:43:41 +0900 (33e9fc3) +++ /dev/null @@ -1,2763 +0,0 @@ -/* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2012 Brazil - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "groonga_in.h" -#include <string.h> -#include "ql.h" -#include "db.h" -#include "pat.h" -#include "snip.h" - -#define DB_OBJ(obj) ((grn_db_obj *)obj) -#define RVALUE(obj) (grn_ctx_at(ctx, (obj)->u.o.id)) -#define INTERN2(s,l) (grn_ql_mk_symbol(ctx, s, l)) - -static grn_cell *ha_object(grn_ctx *ctx, grn_cell *args, grn_ql_co *co); -static grn_cell *ha_snip(grn_ctx *ctx, grn_cell *args, grn_ql_co *co); -static grn_cell *ha_sections(grn_ctx *ctx, grn_cell *args, grn_ql_co *co); - -#define STRBUF_SIZE (GRN_TABLE_MAX_KEY_SIZE + 1) - -static grn_rc -obj2str(grn_cell *o, char *buf, uint16_t *size) -{ - if (SYMBOLP(o)) { - const char *r = _grn_hash_strkey_by_val(o, size); - if (r && *r == ':') { - r++; - (*size)--; - } - memcpy(buf, r, *size); - buf[*size] = '\0'; - } else if (o->header.type == GRN_CELL_STR) { - if (STRSIZE(o) > GRN_TABLE_MAX_KEY_SIZE) { - memcpy(buf, STRVALUE(o), GRN_TABLE_MAX_KEY_SIZE); - buf[GRN_TABLE_MAX_KEY_SIZE] = '\0'; - *size = GRN_TABLE_MAX_KEY_SIZE + 1; - } else { - *size = STRSIZE(o); - memcpy(buf, STRVALUE(o), *size); - buf[*size] = '\0'; - } - } else if (o->header.type == GRN_CELL_INT) { - char *rest; - grn_lltoa(IVALUE(o), buf, buf + GRN_TABLE_MAX_KEY_SIZE, &rest); - *size = rest - buf; - *rest = '\0'; - } else { - return GRN_INVALID_ARGUMENT; - } - return GRN_SUCCESS; -} - -static void -obj_obj_bind(grn_cell *obj, grn_id domain, grn_id self) -{ - obj->header.type = GRN_CELL_OBJECT; - obj->header.impl_flags = GRN_CELL_NATIVE; - obj->u.o.id = self; - obj->header.domain = domain; - obj->u.o.func = ha_object; -} - -static grn_cell * -obj2cell(grn_ctx *ctx, grn_obj *obj, grn_cell *cell) -{ - if (GRN_DB_OBJP(obj)) { - grn_id id = DB_OBJ(obj)->id; - if (id & GRN_OBJ_TMP_OBJECT) { - grn_tmp_db_obj *tmp_obj; - if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, - id & ~GRN_OBJ_TMP_OBJECT))) { - return &tmp_obj->cell; - } else { - return F; - } - } else { - char buf[STRBUF_SIZE]; - int len = grn_obj_name(ctx, obj, buf, STRBUF_SIZE); - return INTERN2(buf, len); - } - } - if (!cell) { if (!(cell = grn_cell_new(ctx))) { return F; } } - switch (obj->header.type) { - case GRN_BULK : - { - void *v = GRN_BULK_HEAD(obj); - grn_id rid = obj->header.domain; - grn_obj *range = grn_ctx_at(ctx, rid); - if (v) { - if (range && range->header.type == GRN_TYPE) { - switch (rid) { - case GRN_DB_INT32 : - SETINT(cell, *((int32_t *)v)); - break; - case GRN_DB_UINT32 : - SETINT(cell, *((uint32_t *)v)); - break; - case GRN_DB_INT64 : - SETINT(cell, *((int64_t *)v)); - break; - case GRN_DB_FLOAT : - SETFLOAT(cell, *((double *)v)); - break; - case GRN_DB_TIME : - SETTIME(cell, v); - break; - default : - { - uint32_t size = GRN_BULK_VSIZE(obj); - void *value = GRN_MALLOC(size); - if (!value) { return F; } - cell->header.impl_flags |= GRN_OBJ_ALLOCATED; - memcpy(value, v, size); - SETBULK(cell, value, size); - } - break; - } - } else { - obj_obj_bind(cell, rid, *((grn_id *)v)); - } - } - } - break; - case GRN_UVECTOR : - { - grn_obj *sections = grn_obj_graft(ctx, obj); - if (sections) { - cell->header.type = GRN_UVECTOR; - cell->header.impl_flags |= GRN_OBJ_ALLOCATED|GRN_CELL_NATIVE; - cell->u.p.value = sections; - cell->u.p.func = ha_sections; - } - } - break; - case GRN_VECTOR : - { - grn_obj *sections = grn_obj_graft(ctx, obj); - if (sections) { - cell->header.type = GRN_VECTOR; - cell->header.impl_flags |= GRN_OBJ_ALLOCATED|GRN_CELL_NATIVE; - cell->u.p.value = sections; - cell->u.p.func = ha_sections; - } - } - break; - } - return cell; -} - -static int -keywordp(grn_cell *x) -{ - uint16_t name_size; - const char *name; - return SYMBOLP(x) - && (name = _grn_hash_strkey_by_val(x, &name_size)) - && name_size - && *name == ':'; -} - -static int -symbolp(grn_cell *x) -{ - uint16_t name_size; - const char *name; - return SYMBOLP(x) - && (name = _grn_hash_strkey_by_val(x, &name_size)) - && (!name_size || *name != ':'); -} - -static int -descp(grn_cell *x) -{ - uint16_t name_size; - const char *name; - return SYMBOLP(x) - && (name = _grn_hash_strkey_by_val(x, &name_size)) - && (name_size > 1) - && (*name == ':') - && (name[1] == 'd'); -} - -/* column_exp */ - -typedef struct { - grn_cell *expr; - grn_table_sort_key *keys; - grn_cell **cells; - int n_keys; - int n_applys; -} column_exp; - -static grn_obj * -get_accessor(grn_ctx *ctx, grn_obj *table, grn_cell *e) -{ - uint16_t msg_size; - char msg[STRBUF_SIZE]; - obj2str(e, msg, &msg_size); - return grn_obj_column(ctx, table, msg, msg_size); -} - -#define COLUMN_EXPP(x,ce) ((x) == (ce)->cells[(ce)->n_keys]) - -static grn_cell * -column_exp_build_(grn_ctx *ctx, grn_obj *table, grn_cell *e, column_exp *ce, grn_cell *parameter) -{ - if (PAIRP(e)) { - grn_cell *x, *r, *l = NIL, **d; - POP(x, e); - if (x == parameter && keywordp(CAR(e))) { - if (ce->keys[ce->n_keys].key) { ce->n_keys++; } - ce->keys[ce->n_keys].key = get_accessor(ctx, table, CAR(e)); - d = &ce->cells[ce->n_keys]; - if (!*d) { *d = grn_cell_new(ctx); } - r = *d; - } else { - r = column_exp_build_(ctx, table, x, ce, parameter); - if (COLUMN_EXPP(r, ce) && keywordp(CAR(e))) { - get_accessor(ctx, ce->keys[ce->n_keys].key, CAR(e)); - } else { - r = CONS(r, NIL); - d = &CDR(r); - while (PAIRP(e)) { - POP(x, e); - if (COLUMN_EXPP(l, ce) && descp(x)) { - ce->keys[ce->n_keys].flags |= GRN_TABLE_SORT_DESC; - } - l = column_exp_build_(ctx, table, x, ce, parameter); - *d = CONS(l, NIL); - d = &CDR(*d); - } - } - } - return r; - } else { - return e; - } -} - -static void -column_exp_build(grn_ctx *ctx, grn_obj *table, grn_cell *e, column_exp *ce, grn_cell *parameter) -{ - grn_cell *x, *r = e, *l = NIL, **d = &r; - ce->n_keys = 0; - while (PAIRP(e)) { - POP(x, e); - if (COLUMN_EXPP(l, ce) && descp(x)) { - ce->keys[ce->n_keys].flags |= GRN_TABLE_SORT_DESC; - } - l = column_exp_build_(ctx, table, x, ce, parameter); - *d = CONS(l, NIL); - d = &CDR(*d); - } - if (ce->keys[ce->n_keys].key) { ce->n_keys++; } - ce->expr = r; - grn_ql_obj_mark(ctx, ce->expr); -} - -#define EVAL_BY_FUNCALLP(ce) \ - ((ce)->n_applys == 1 && PAIRP((ce)->expr) && NATIVE_FUNCP(CAR((ce)->expr))) - -static void -column_exp_check(grn_cell *e, int *ns, int *ne, grn_cell *parameter) -{ - if (PAIRP(e)) { - grn_cell *x; - POP(x, e); - if (x == parameter) { - (*ns)++; - } else if (NATIVE_FUNCP(x)) { - (*ne)++; - } else { - column_exp_check(x, ns, ne, parameter); - } - while (PAIRP(e)) { - POP(x, e); - column_exp_check(x, ns, ne, parameter); - } - } else { - if (symbolp(e)) { (*ne)++; } - } -} - -static column_exp * -column_exp_open(grn_ctx *ctx, grn_obj *table, grn_cell *expr, grn_cell *parameter) -{ - column_exp *ce = GRN_CALLOC(sizeof(column_exp)); - if (ce) { - column_exp_check(expr, &ce->n_keys, &ce->n_applys, parameter); - if (ce->n_keys) { - if (!(ce->keys = GRN_CALLOC(sizeof(grn_table_sort_key) * ce->n_keys))) { - GRN_FREE(ce); - return NULL; - } - if (!(ce->cells = GRN_CALLOC(sizeof(grn_cell *) * ce->n_keys))) { - GRN_FREE(ce->keys); - GRN_FREE(ce); - return NULL; - } - column_exp_build(ctx, table, expr, ce, parameter); - } else { - ce->expr = expr; - } - } - return ce; -} - -static grn_rc -column_exp_exec(grn_ctx *ctx, column_exp *ce, grn_id id) -{ - int i; - grn_obj v, *vp; - GRN_TEXT_INIT(&v, 0); - for (i = 0; i < ce->n_keys; i++) { - grn_cell *c = ce->cells[i]; - GRN_BULK_REWIND(&v); - vp = grn_obj_get_value(ctx, ce->keys[i].key, id, &v); - grn_cell_clear(ctx, c); - obj2cell(ctx, vp, c); - } - grn_obj_close(ctx, &v); - return GRN_SUCCESS; -} - -static grn_rc -column_exp_close(grn_ctx *ctx, column_exp *ce) -{ - int i; - grn_ql_obj_unmark(ctx, ce->expr); - for (i = 0; i < ce->n_keys; i++) { - grn_obj_unlink(ctx, ce->keys[i].key); - } - if (ce->keys) { GRN_FREE(ce->keys); } - if (ce->cells) { GRN_FREE(ce->cells); } - GRN_FREE(ce); - return GRN_SUCCESS; -} - -static grn_cell * -ha_void(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (!ctx->impl->code) { return F; } - return ctx->impl->code; -} - -grn_cell * -grn_ql_obj_new(grn_ctx *ctx, grn_id domain, grn_id self) -{ - grn_cell *o; - GRN_CELL_NEW(ctx, o); - obj_obj_bind(o, domain, self); - return o; -} - -static grn_cell * -get_cell(grn_ctx *ctx, grn_obj *db_obj) -{ - if (db_obj) { - grn_id id = DB_OBJ(db_obj)->id; - if (id & GRN_OBJ_TMP_OBJECT) { - grn_tmp_db_obj *tmp_obj; - if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, - id & ~GRN_OBJ_TMP_OBJECT))) { - return &tmp_obj->cell; - } else { - return F; - } - } else { - char buf[STRBUF_SIZE]; - int len = grn_obj_name(ctx, db_obj, buf, STRBUF_SIZE); - return INTERN2(buf, len); - } - } else { - return F; - } -} - -static grn_obj * -get_obj(grn_ctx *ctx, grn_cell *cell) -{ - return GRN_DB_OBJP(cell) ? grn_ctx_at(ctx, cell->u.o.id) : NULL; -} - -static grn_obj * -get_domain(grn_ctx *ctx, grn_cell *cell) -{ - return grn_ctx_at(ctx, cell->header.domain); -} - -static void -unesc(grn_ctx *ctx, grn_cell *obj) -{ - char *src, *dest, *end = STRVALUE(obj) + STRSIZE(obj); - for (src = dest = STRVALUE(obj);;) { - unsigned int len; - if (!(len = grn_charlen(ctx, src, end))) { break; } - if (src[0] == '\\' && src + 1 < end && len == 1) { - src++; - switch (*src) { - case 'n' : - *dest++ = '\n'; - break; - case 'r' : - *dest++ = '\r'; - break; - case 't' : - *dest++ = '\t'; - break; - default : - *dest++ = *src; - break; - } - src++; - } else { - while (len--) { *dest++ = *src++; } - } - } - STRSIZE(obj) = dest - STRVALUE(obj); -} - -static grn_cell * -grn_ql_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, grn_cell *res) -{ - grn_id id = grn_table_add(ctx, table, key, key_size, NULL); - if (id) { - if (!res) { GRN_CELL_NEW(ctx, res); } - obj_obj_bind(res, DB_OBJ(table)->id, id); - return res; - } else { - return F; - } -} - -static grn_cell * -grn_ql_table_get(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, grn_cell *res) -{ - grn_id id = grn_table_get(ctx, table, key, key_size); - if (id) { - if (!res) { GRN_CELL_NEW(ctx, res); } - obj_obj_bind(res, DB_OBJ(table)->id, id); - return res; - } else { - return F; - } -} - -static grn_obj * -get_column(grn_ctx *ctx, grn_id tid, char *msg, unsigned int msg_size, grn_id *id) -{ - grn_obj *table = grn_ctx_at(ctx, tid); - for (;;) { - grn_obj *domain = grn_ctx_at(ctx, DB_OBJ(table)->header.domain); - if (!domain || domain->header.type == GRN_TYPE) { break; } - if (id) { - if (!grn_table_get_key(ctx, table, *id, id, sizeof(grn_id))) { return NULL; } - } - table = domain; - } - return grn_obj_column(ctx, table, msg, msg_size); -} - -static grn_cell * -table_column(grn_ctx *ctx, grn_id base, char *msg, unsigned int msg_size) -{ - grn_obj *column = get_column(ctx, base, msg, msg_size, NULL); - return column ? get_cell(ctx, column) : F; -} - -static grn_cell * -ha_sections(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - uint16_t msg_size; - grn_cell *car, *res; - char msg[STRBUF_SIZE]; - if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); } - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - switch (*msg) { - case ':' : - switch (msg[1]) { - case 's' : /* :sexp */ - { - grn_obj *sections = (grn_obj *)res->u.p.value; - int n = sections->u.v.n_sections; - grn_section *vp = §ions->u.v.sections[n]; - const char *head = GRN_BULK_HEAD(sections->u.v.body); - grn_cell *a = INTERN("@"); - grn_cell *d = INTERN(":dic"); - grn_cell *w = INTERN(":weight"); - grn_cell *v = INTERN(":value"); - res = NIL; - while ((vp--, n--)) { - grn_cell *vs = NIL; - if (vp->weight || vp->domain) { - vs = CONS(v, CONS(grn_ql_mk_string(ctx, head + vp->offset, vp->length), vs)); - if (vp->weight) { - grn_cell *nv; - GRN_CELL_NEW(ctx, nv); - SETINT(nv, vp->weight); - vs = CONS(w, CONS(nv, vs)); - } - if (vp->domain) { - grn_cell *nv; - GRN_CELL_NEW(ctx, nv); - SETINT(nv, vp->domain); - vs = CONS(d, CONS(nv, vs)); - } - vs = CONS(a, vs); - } else { - vs = grn_ql_mk_string(ctx, head + vp->offset, vp->length); - } - res = CONS(vs, res); - } - } - break; - default : - QLERR("invalid argument"); - } - break; - default : - QLERR("invalid argument"); - } - return res; -} - -#define QLWARN(...) ERRSET(ctx, GRN_WARN, GRN_INVALID_ARGUMENT, __VA_ARGS__) - -#define STR2DBL(str,len,val) do {\ - char *end, buf0[128], *buf = (len) < 128 ? buf0 : GRN_MALLOC((len) + 1);\ - if (buf) {\ - double d;\ - memcpy(buf, (str), (len));\ - buf[len] = '\0';\ - errno = 0;\ - d = strtod(buf, &end);\ - if (!((len) < 128)) { GRN_FREE(buf); }\ - if (!errno && buf + (len) == end) {\ - (val) = d;\ - } else { QLWARN("cast failed"); }\ - } else { QLWARN("buf alloc failed"); }\ -} while (0) - -static void -list2vector(grn_ctx *ctx, grn_cell *s, grn_obj *v) -{ - grn_cell *car, *key, *value; - while (PAIRP(s)) { - POP(car, s); - if (BULKP(car)) { - grn_vector_add_element(ctx, v, STRVALUE(car), STRSIZE(car), 0, GRN_ID_NIL); - } else if (PAIRP(car)) { - const char *str = NULL; - grn_id domain = GRN_ID_NIL; - unsigned int weight = 0, str_len = 0; - POP(key, car); - if (key == INTERN("@")) { - while (PAIRP(car)) { - POP(key, car); - POP(value, car); - if (key == INTERN(":dic")) { - /* todo */ - } else if (key == INTERN(":weight")) { - grn_obj2int(ctx, value); - weight = (uint32_t) IVALUE(value); - } else if (key == INTERN(":value") && BULKP(value)) { - str = STRVALUE(value); - str_len = STRSIZE(value); - } - } - if (str) { - grn_vector_add_element(ctx, v, str, str_len, weight, domain); - } - } - } - } -} - -static grn_obj * -cell2obj(grn_ctx *ctx, grn_cell *cell, grn_obj *column, grn_obj *obj) -{ - if ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_SCALAR) { - grn_id rid = grn_obj_get_range(ctx, column); - grn_obj *range = grn_ctx_at(ctx, rid); - if (range && range->header.type == GRN_TYPE) { - switch (rid) { - case GRN_DB_INT32 : - { - int32_t v; - switch (cell->header.type) { - case GRN_CELL_STR : - { - int64_t iv = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL); - v = (int32_t) iv; - } - break; - case GRN_CELL_INT : - v = (int32_t) IVALUE(cell); - break; - case GRN_CELL_FLOAT : - v = (int32_t) FVALUE(cell); - break; - case GRN_CELL_TIME : - v = (int32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC; - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(int32_t)); - } - break; - case GRN_DB_UINT32 : - { - uint32_t v; - switch (cell->header.type) { - case GRN_CELL_STR : - { - int64_t iv = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL); - v = (uint32_t) iv; - } - break; - case GRN_CELL_INT : - v = (uint32_t) IVALUE(cell); - break; - case GRN_CELL_FLOAT : - v = (uint32_t) FVALUE(cell); - break; - case GRN_CELL_TIME : - v = (uint32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC; - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(uint32_t)); - } - break; - case GRN_DB_INT64 : - { - int64_t v; - switch (cell->header.type) { - case GRN_CELL_STR : - v = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL); - break; - case GRN_CELL_INT : - v = IVALUE(cell); - break; - case GRN_CELL_FLOAT : - v = (int64_t) FVALUE(cell); - break; - case GRN_CELL_TIME : - v = (int32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC; - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(int64_t)); - } - break; - case GRN_DB_FLOAT : - { - double v; - switch (cell->header.type) { - case GRN_CELL_STR : - { /* todo : support #i notation */ - char *str = STRVALUE(cell); - int len = STRSIZE(cell); - STR2DBL(str, len, v); - } - break; - case GRN_CELL_INT : - v = (double) IVALUE(cell); - break; - case GRN_CELL_FLOAT : - v = FVALUE(cell); - break; - case GRN_CELL_TIME : - v = ((double) cell->u.tv.tv_nsec) / GRN_TIME_NSEC_PER_SEC + cell->u.tv.tv_sec; - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(double)); - } - break; - case GRN_DB_TIME : - { - grn_timeval v; - switch (cell->header.type) { - case GRN_CELL_STR : - { - int len = STRSIZE(cell); - char *str = STRVALUE(cell); - if (grn_str2timeval(str, len, &v)) { - if (len > 3 && *str == '#' && str[1] == ':' && str[2] == '<') { - const char *cur; - v.tv_sec = grn_atoi(str + 3, str + len, &cur); - if (cur >= str + len || *cur != '.') { - QLWARN("illegal time format '%s'", str); - } - v.tv_nsec = grn_atoi(cur + 1, str + len, &cur); - if (cur >= str + len || *cur != '>') { - QLWARN("illegal time format '%s'", str); - } - } else { - double dval = 0.0; - char *str = STRVALUE(cell); - int len = cell->u.b.size; - STR2DBL(str, len, dval); - v.tv_sec = (int32_t) dval; - v.tv_nsec = (int32_t) ((dval - v.tv_sec) * GRN_TIME_NSEC_PER_SEC); - } - } - } - break; - case GRN_CELL_INT : - v.tv_sec = (int32_t) IVALUE(cell); - v.tv_nsec = 0; - break; - case GRN_CELL_FLOAT : - v.tv_sec = (int32_t) FVALUE(cell); - v.tv_nsec = (int32_t) ((FVALUE(cell) - v.tv_sec) * GRN_TIME_NSEC_PER_SEC); - break; - case GRN_CELL_TIME : - v.tv_sec = cell->u.tv.tv_sec; - v.tv_nsec = cell->u.tv.tv_nsec; - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(grn_timeval)); - } - break; - default : - if (BULKP(cell)) { - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, STRVALUE(cell), STRSIZE(cell)); - } else { - if (obj) { GRN_BULK_REWIND(obj); } - } - break; - } - } else { - /* todo : grn_type_any support - grn_bulk_write(ctx, bulk, (const char *)(&cell->header.domain), sizeof(grn_id)); - */ - /* todo : nested table support. - */ - grn_id id; - switch (cell->header.type) { - case GRN_CELL_OBJECT : - if (cell->header.domain != rid) { return NULL; } - id = cell->u.o.id; - break; - case GRN_CELL_STR : - id = grn_table_add(ctx, range, STRVALUE(cell), STRSIZE(cell), NULL); - break; - default : - if (VOIDP(cell)) { id = GRN_ID_NIL; } - break; - } - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, (const char *)&id, sizeof(grn_id)); - } - obj->header.domain = rid; - } else { - switch (cell->header.type) { - case GRN_CELL_STR : - if (BULKP(cell)) { - if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }} - grn_bulk_write(ctx, obj, STRVALUE(cell), STRSIZE(cell)); - } else { - if (obj) { GRN_BULK_REWIND(obj); } - } - /* todo */ - break; - case GRN_CELL_INT : - /* todo */ - break; - case GRN_CELL_FLOAT : - /* todo */ - break; - case GRN_CELL_TIME : - /* todo */ - break; - case GRN_CELL_LIST : - obj = grn_obj_open(ctx, GRN_VECTOR, 0, 0); - list2vector(ctx, cell, obj); - break; - case GRN_VECTOR : - obj = (grn_obj *)cell->u.p.value; - break; - } - } - return obj; -} - -inline static grn_cell * -column_value(grn_ctx *ctx, grn_obj *column, grn_id obj, - grn_cell *args, grn_cell *res) -{ - grn_obj *value; - if (!column) { return F; } - if (VOIDP(args) || (PAIRP(args) && VOIDP(CAR(args)))) { - if ((value = grn_obj_get_value(ctx, column, obj, NULL))) { - switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { - case GRN_OBJ_COLUMN_VECTOR : - { - grn_cell **rp = &res; - grn_id *v = (grn_id *) GRN_BULK_HEAD(value); - uint32_t s = GRN_BULK_VSIZE(value) / sizeof(grn_id); - *rp = NIL; - while (s--) { - grn_cell *cell = grn_cell_new(ctx); - if (cell) { - obj_obj_bind(cell, column->header.domain, *v); - if ((*rp = CONS(cell, NIL))) { - rp = &CDR(*rp); - } - } - } - } - break; - default : - res = obj2cell(ctx, value, res); - break; - } - grn_obj_close(ctx, value); - } else { - res = F; - } - } else { - grn_cell *car; - int flags = GRN_OBJ_SET; - POP(car, args); - if ((value = cell2obj(ctx, car, column, NULL))) { - res = grn_obj_set_value(ctx, column, obj, value, flags) ? F : car; - grn_obj_close(ctx, value); - } else { - res = F; - } - } - return res; -} - -static grn_cell * -register_cell(grn_ctx *ctx, grn_obj *db_obj, const char *name, unsigned int name_size) -{ - if (name && name_size) { - return INTERN2(name, name_size); - // grn_ql_obj_bind(db_obj, res); - } else { - grn_cell *r = get_cell(ctx, db_obj); - if (r != F) { - r->header.impl_flags = 0; - r->header.flags = 0; - grn_ql_obj_bind(db_obj, r); - } - return r; - } -} - -static grn_cell * -table_create(grn_ctx *ctx, const char *name, unsigned int name_size, - grn_obj_flags flags, grn_obj *domain, - grn_obj *value_type, grn_id tokenizer) -{ - grn_obj *table = grn_table_create(ctx, name, name_size, - NULL, flags, domain, value_type); - if (!table) { QLERR("table create failed"); } - grn_obj_set_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, grn_ctx_at(ctx, tokenizer)); - return register_cell(ctx, table, name, name_size); -} - -static grn_cell * -rec_obj_new(grn_ctx *ctx, grn_obj *domain, grn_obj *value_type) -{ - return table_create(ctx, NULL, 0, GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, - domain, value_type, GRN_DB_DELIMIT); -} - -typedef struct { - column_exp *ce; - grn_cell *func; - // grn_cell *exprs; - grn_cell *args; - grn_operator op; - // grn_cell *objs; - int32_t offset; - int32_t limit; - int mode; - char *from; - unsigned int fromsize; - char *to; - unsigned int tosize; - column_exp *score_ce; - grn_cell *score_func; -} match_spec; - -inline static grn_cell * -match_prepare(grn_ctx *ctx, match_spec *spec, grn_id base, grn_cell *args) -{ - grn_cell *car, *expr; - grn_obj *r = grn_ctx_at(ctx, base); - POP(expr, args); - spec->ce = column_exp_open(ctx, r, expr, NIL); - if (EVAL_BY_FUNCALLP(spec->ce)) { - spec->func = CAR(expr); - } else { - spec->func = NULL; - } - spec->offset = 0; - spec->limit = 0; - spec->mode = 0; - spec->from = NULL; - spec->fromsize = 0; - spec->to = NULL; - spec->tosize = 0; - spec->op = GRN_OP_OR; - spec->score_ce = NULL; - spec->score_func = NULL; - POP(car, args); - if (car != NIL) { - spec->score_ce = column_exp_open(ctx, r, car, NIL); - if (EVAL_BY_FUNCALLP(spec->score_ce)) { spec->score_func = CAR(car); } - } - POP(expr, args); - if (RECORDSP(expr)) { - char ops[STRBUF_SIZE]; - uint16_t ops_size; - if (expr->header.domain != base) { QLERR("table unmatch"); } - POP(car, args); - spec->op = GRN_OP_AND; - if (!obj2str(car, ops, &ops_size)) { - switch (*ops) { - case '+': spec->op = GRN_OP_OR; break; - case '-': spec->op = GRN_OP_BUT; break; - case '*': spec->op = GRN_OP_AND; break; - case '>': spec->op = GRN_OP_ADJUST; break; - } - } - } else { - char str[STRBUF_SIZE]; - uint16_t str_size; - grn_obj *table = grn_ctx_at(ctx, base); - if (INTP(expr)) { spec->offset = IVALUE(expr); } - POP(expr, args); - if (INTP(expr)) { spec->limit = IVALUE(expr); } - if (spec->limit <= 0) { spec->limit += grn_table_size(ctx, table); } - POP(expr, args); - if (!obj2str(expr, str, &str_size)) { - uint16_t i; - for (i = 0; i < str_size; i++) { - switch (str[i]) { - case 'd' : spec->mode |= GRN_CURSOR_DESCENDING; break; - case 'g' : spec->mode |= GRN_CURSOR_GT; break; - case 'l' : spec->mode |= GRN_CURSOR_LT; break; - } - } - } - POP(expr, args); - if (BULKP(expr)) { - spec->from = STRVALUE(expr); - spec->fromsize = STRSIZE(expr); - } - POP(expr, args); - if (BULKP(expr)) { - spec->to = STRVALUE(expr); - spec->tosize = STRSIZE(expr); - } - expr = rec_obj_new(ctx, table, NULL); - if (ERRP(ctx, GRN_WARN)) { return F; } - spec->op = GRN_OP_OR; - } - // spec->objs = CONS(expr, spec->exprs); - return expr; -} - -grn_obj * -grn_ql_obj_key(grn_ctx *ctx, grn_cell *obj, grn_obj *value) -{ - grn_obj *table = grn_ctx_at(ctx, obj->header.domain); - grn_obj *accessor = grn_obj_column(ctx, table, ":key", 4); - if (accessor) { - value = grn_obj_get_value(ctx, accessor, obj->u.o.id, value); - grn_obj_unlink(ctx, accessor); - } - return value; -} - -inline static grn_cell * -obj2oid(grn_ctx *ctx, grn_cell *obj, grn_cell *res) -{ - grn_obj buf; - if (obj->header.type != GRN_CELL_OBJECT) { return F; } - GRN_TEXT_INIT(&buf, 0); - grn_obj_inspect(ctx, obj, &buf, GRN_OBJ_INSPECT_ESC); - if (res) { - uint32_t size = GRN_BULK_VSIZE(&buf); - char *value = GRN_MALLOC(size + 1); - if (!value) { - res = F; - goto exit; - } - grn_cell_clear(ctx, res); - res->header.impl_flags = GRN_OBJ_ALLOCATED; - res->header.type = GRN_CELL_STR; - res->u.b.size = size; - res->u.b.value = value; - memcpy(res->u.b.value, GRN_TEXT_VALUE(&buf), res->u.b.size + 1); - } else { - if (!(res = grn_ql_mk_string(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_VSIZE(&buf)))) { - res = F; - } - } -exit : - GRN_OBJ_FIN(ctx, &buf); - return res; -} - -inline static int -match_exec(grn_ctx *ctx, match_spec *spec, grn_id base, grn_id id) -{ - grn_cell *res; - column_exp_exec(ctx, spec->ce, id); - if (spec->func) { - grn_cell *code = ctx->impl->code; - ctx->impl->code = spec->func; - res = spec->func->u.o.func(ctx, CDR(spec->ce->expr), &ctx->impl->co); - ctx->impl->code = code; - } else { - res = grn_ql_eval(ctx, spec->ce->expr, NIL); - } - return res != F; -} - -inline static int -score_exec(grn_ctx *ctx, match_spec *spec, grn_id base, grn_id id) -{ - grn_cell *res; - column_exp_exec(ctx, spec->score_ce, id); - if (spec->score_func) { - grn_cell *code = ctx->impl->code; - ctx->impl->code = spec->score_func; - res = spec->score_func->u.o.func(ctx, CDR(spec->score_ce->expr), &ctx->impl->co); - ctx->impl->code = code; - } else { - res = grn_ql_eval(ctx, spec->score_ce->expr, NIL); - } - switch (res->header.type) { - case GRN_CELL_INT : - return IVALUE(res); - case GRN_CELL_FLOAT : - return (int)FVALUE(res); - default : - return 0; - } -} - -static grn_rc -match_close(grn_ctx *ctx, match_spec *spec) -{ - if (spec->score_ce) { column_exp_close(ctx, spec->score_ce); } - return column_exp_close(ctx, spec->ce); -} - -// todo : refine -#define MAXCOLUMNS 0x100 - -struct _ins_stat { - grn_cell *columns; - int ncolumns; - int nrecs; -}; - -typedef struct { - grn_encoding encoding; - char *cur; - char *str_end; -} jctx; - -static grn_cell *json_read(grn_ctx *ctx, jctx *jc, int keyp); - -static grn_cell * -ha_table(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_id base; - int load = 0; - grn_obj *table; - grn_cell *car, *res; - char msg[STRBUF_SIZE]; - uint16_t msg_size; - if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); } - base = ctx->impl->code->u.o.id; - if (!(table = grn_ctx_at(ctx, base))) { QLERR("invalid table"); } - GRN_QL_CO_BEGIN(co); - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - switch (*msg) { - case '\0' : /* get instance by key */ - { - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - res = grn_ql_table_get(ctx, table, msg, msg_size, NULL); - } - break; - case ':' : - switch (msg[1]) { - case 'c' : - case 'C' : - switch (msg[2]) { - case 'l' : /* :clearlock */ - case 'L' : - { - res = grn_obj_is_locked(ctx, table) ? T : F; - grn_obj_clear_lock(ctx, table); - } - break; - case 'o' : /* :common-prefix-search */ - case 'O' : - switch (msg[3]) { - case 'm' : - case 'M' : - { - grn_id id; - POP(car, args); - if (!BULKP(car)) { QLERR("invalid argument"); } - id = grn_table_lcp_search(ctx, table, STRVALUE(car), STRSIZE(car)); - res = id ? grn_ql_obj_new(ctx, base, id) : F; - } - break; - case 'l' : /* :columns */ - case 'L' : - POP(car, args); - if (RECORDSP(car)) { - msg_size = 0; - res = car; - } else { - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - POP(res, args); - if (res == NIL) { - if (!(res = rec_obj_new(ctx, NULL, NULL))) { QLERR("rec_obj_new failed"); } - } else if (!RECORDSP(res)) { - QLERR("records object expected"); - } - } - grn_table_columns(ctx, table, msg, msg_size, get_obj(ctx, res)); - break; - default : - res = F; - break; - } - break; - } - break; - case 'd' : - case 'D' : - switch (msg[2]) { - case 'e' : - case 'E' : - switch (msg[3]) { - case 'f' : /* :def */ - case 'F' : - { - uint16_t name_size; - int nsources = 0; - grn_id sources[MAXCOLUMNS]; - grn_obj *column, *type; - char name[STRBUF_SIZE]; - grn_obj_flags flags = GRN_OBJ_PERSISTENT; /* default */ - POP(car, args); - if (obj2str(car, name, &name_size)) { QLERR("invalid argument"); } - if (grn_obj_column(ctx, table, name, name_size)) { return T; } - POP(car, args); - type = get_obj(ctx, car); - while (PAIRP(args)) { - POP(car, args); - if (PAIRP(car)) { - grn_cell *col; - while (PAIRP(car) && nsources < MAXCOLUMNS) { - POP(col, car); - if (!obj2str(col, msg, &msg_size)) { - grn_obj *source = grn_obj_column(ctx, type, msg, msg_size); - if (source) { sources[nsources++] = DB_OBJ(source)->id; } - } - } - } else { - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - switch (*msg) { - case 'b' : - case 'B' : - flags |= GRN_OBJ_RING_BUFFER; - break; - case 'i' : - case 'I' : - flags |= GRN_OBJ_COLUMN_INDEX; - break; - case 'l' : - case 'L' : - flags |= GRN_OBJ_COMPRESS_LZO; - break; - case 'p' : - case 'P' : - switch (msg[1]) { - case 'e' : - case 'E' : - flags |= GRN_OBJ_PERSISTENT; - break; - case 'o' : - case 'O' : - flags |= GRN_OBJ_WITH_POSITION; - break; - } - break; - case 's' : - case 'S' : - flags |= GRN_OBJ_WITH_SECTION; - break; - case 't' : - case 'T' : - flags &= ~GRN_OBJ_PERSISTENT; - break; - case 'v' : - case 'V' : - flags |= GRN_OBJ_COLUMN_VECTOR; - break; - case 'w' : - case 'W' : - flags |= GRN_OBJ_WITH_WEIGHT; - break; - case 'z' : - case 'Z' : - flags |= GRN_OBJ_COMPRESS_ZLIB; - break; - } - } - } - column = grn_column_create(ctx, table, name, name_size, NULL, flags, type); - if (column) { - if (nsources) { - grn_obj source; - GRN_TEXT_INIT(&source, GRN_OBJ_DO_SHALLOW_COPY); - GRN_TEXT_SET_REF(&source, sources, nsources * sizeof(grn_id)); - grn_obj_set_info(ctx, column, GRN_INFO_SOURCE, &source); - } - msg_size = grn_obj_name(ctx, column, msg, GRN_PAT_MAX_KEY_SIZE); - res = INTERN2(msg, msg_size); - } else { - res = F; - } - } - break; - case 'l' : /* :delete */ - case 'L' : - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - res = grn_table_delete(ctx, table, msg, msg_size) ? T : F; - break; - default : - res = F; - break; - } - break; - case 'i' : /* :difference */ - case 'I' : - { - if (PAIRP(args)) { - POP(car, args); - if (TABLEP(car)) { - grn_obj *table2 = RVALUE(car); - res = grn_table_difference(ctx, table, table2, table, table2) ? T : F; - } - } - } - break; - default : - res = F; - break; - } - break; - case 'e' : /* :extract */ - case 'E' : - POP(car, args); - if (!BULKP(car)) { QLERR("string expected"); } - POP(res, args); - if (res == NIL) { - if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); } - } else if (!RECORDSP(res)) { - QLERR("records object expected"); - } - if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car), - GRN_OP_TERM_EXTRACT, get_obj(ctx, res), GRN_OP_OR) - < GRN_SUCCESS) { - QLERR("term_extract failed"); - } - break; - case 'g' : /* :group */ - case 'G' : - { - column_exp *ce; - POP(car, args); - ce = column_exp_open(ctx, table, car, NIL); - if (ce) { - int n_results = 0; - grn_table_group_result *rp, results[256]; - POP(car, args); - for (rp = results; TABLEP(car); rp++) { - memset(rp, 0, sizeof(grn_table_group_result)); - rp->table = get_obj(ctx, car); - POP(car, args); - if (INTP(car)) { - rp->key_begin = IVALUE(car); - POP(car, args); - if (INTP(car)) { - rp->key_end = IVALUE(car); - } else { - rp->key_end = rp->key_begin + 1; - } - } else { - rp->key_begin = n_results; - rp->key_end = rp->key_begin + 1; - } - if (++n_results >= 256) { break; } - } - if (!n_results) { - for (rp = results; n_results < ce->n_keys; rp++, n_results++) { - grn_id range = grn_obj_get_range(ctx, ce->keys[n_results].key); - rp->table = get_obj(ctx, rec_obj_new(ctx, grn_ctx_at(ctx, range), NULL)); - rp->key_begin = n_results; - rp->key_end = rp->key_begin + 1; - } - } - grn_table_group(ctx, table, ce->keys, ce->n_keys, results, n_results); - column_exp_close(ctx, ce); - res = NIL; - while (n_results--) { - res = CONS(get_cell(ctx, results[n_results].table), res); - } - } else { - QLERR("group key parse error"); - } - } - break; - case 'i' : /* :intersect */ - case 'I' : - { - while (PAIRP(args)) { - POP(car, args); - if (!TABLEP(car)) { continue; } - grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_AND); - } - } - break; - case 'j' : /* :jload */ - case 'J' : - load = 1; - break; - case 'l' : /* :load */ - case 'L' : - load = 2; - break; - case 'n' : - case 'N' : - { - switch (msg[2]) { - case 'e' : /* :new */ - case 'E' : - { - // todo : support array - POP(car, args); - if (obj2str(car, msg, &msg_size)) { return F; } - res = grn_ql_table_add(ctx, table, msg, msg_size, NULL); - if (res != F) { - grn_cell cons, dummy; - grn_obj *column; - cons.header.type = GRN_CELL_LIST; - cons.header.impl_flags = 0; - cons.u.l.cdr = NIL; - while (PAIRP(args)) { - POP(car, args); - if (obj2str(car, msg, &msg_size)) { break; } - POP(car, args); - cons.u.l.car = car; - column = grn_obj_column(ctx, table, msg, msg_size); - column_value(ctx, column, res->u.o.id, &cons, &dummy); - } - } - } - break; - case 'r' : /* :nrecs */ - case 'R' : - GRN_CELL_NEW(ctx, res); - SETINT(res, grn_table_size(ctx, table)); - break; - default : - /* ambiguous message. todo : return error */ - res = F; - } - } - break; - case 'p' : /* :prefix-search */ - case 'P' : - POP(car, args); - if (!BULKP(car)) { QLERR("string expected"); } - POP(res, args); - if (res == NIL) { - if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); } - } else if (!RECORDSP(res)) { - QLERR("records object expected"); - } - if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car), - GRN_OP_PREFIX, get_obj(ctx, res), GRN_OP_OR) - < GRN_SUCCESS) { - QLERR("prefix search failed"); - } - break; - case 's' : - case 'S' : - switch (msg[2]) { - case 'c' : - case 'C' : - switch (msg[3]) { - case 'a' : /* :scan-select */ - case 'A' : - { - grn_rset_recinfo *ri; - grn_id *rid; - match_spec spec; - grn_obj *rec; - res = match_prepare(ctx, &spec, base, args); - if (ERRP(ctx, GRN_WARN)) { return F; } - rec = RVALUE(res); - switch (spec.op) { - case GRN_OP_OR : - { - grn_id id; - grn_table_cursor *c; - grn_rset_posinfo *pi = (grn_rset_posinfo *) &id; - int n = 0, o = spec.offset, l = spec.limit; - if (l) { - if ((c = grn_table_cursor_open(ctx, table, - spec.from, spec.fromsize, - spec.to, spec.tosize, 0, -1, - spec.mode))) { - while ((id = grn_table_cursor_next(ctx, c))) { - if (match_exec(ctx, &spec, base, id)) { - if (n++ >= o) { - /* todo : use GRN_SET_INT_ADD if !n_entries */ - grn_table_add_v(ctx, rec, pi, sizeof(grn_id), (void **)&ri, NULL); - if (spec.score_ce) { - int score = score_exec(ctx, &spec, base, id); - grn_table_add_subrec(rec, ri, score, NULL, 0); - } - if (!--l) { break; } - } - } - } - grn_table_cursor_close(ctx, c); - } - } - } - break; - case GRN_OP_AND : - GRN_HASH_EACH(ctx, (grn_hash *)rec, id, &rid, NULL, &ri, { - if (!match_exec(ctx, &spec, base, *rid)) { - grn_hash_delete_by_id(ctx, (grn_hash *)rec, id, NULL); - } - }); - break; - case GRN_OP_BUT : - GRN_HASH_EACH(ctx, (grn_hash *)rec, id, &rid, NULL, &ri, { - if (match_exec(ctx, &spec, base, *rid)) { - grn_hash_delete_by_id(ctx, (grn_hash *)rec, id, NULL); - } - }); - break; - case GRN_OP_ADJUST : - /* todo : support it */ - break; - default : - break; - } - match_close(ctx, &spec); - } - break; - case 'h' : /* :schema */ - case 'H' : - { - grn_obj_flags flags; - grn_encoding encoding; - grn_obj *tokenizer; - res = NIL; - if (!(msg_size = grn_obj_name(ctx, table, msg, STRBUF_SIZE))) { - return F; - } - if (grn_table_get_info(ctx, table, &flags, &encoding, &tokenizer)) { - return F; - } - if (flags & GRN_OBJ_KEY_NORMALIZE) { res = CONS(INTERN(":normalize"), res); } - switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { - case GRN_OBJ_TABLE_HASH_KEY : - res = CONS(INTERN(":hash"), res); - break; - case GRN_OBJ_TABLE_PAT_KEY : - res = CONS(INTERN(":pat"), res); - break; - case GRN_OBJ_TABLE_NO_KEY : - res = CONS(INTERN(":surrogate"), res); - break; - } - { - char encstr[32] = ":"; - strcpy(encstr + 1, grn_enctostr(encoding)); - res = CONS(INTERN(encstr), res); - } - res = CONS(INTERN("ptable"), - CONS(CONS(INTERN("quote"), - CONS(INTERN2(msg, msg_size), NIL)), res)); - } - break; - default : - res = F; - break; - } - break; - case 'o' : /* :sort */ - case 'O' : - { - int limit = 0; - column_exp *ce; - POP(car, args); - ce = column_exp_open(ctx, table, car, NIL); - POP(car, args); - if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; } - if (limit <= 0) { limit += grn_table_size(ctx, table); } - POP(res, args); - if (!RECORDSP(res)) { - res = table_create(ctx, NULL, 0, GRN_OBJ_TABLE_NO_KEY, - NULL, table, GRN_DB_DELIMIT); - } - if (ce) { - grn_table_sort(ctx, table, 0, limit, get_obj(ctx, res), ce->keys, ce->n_keys); - column_exp_close(ctx, ce); - } else { - grn_table_sort(ctx, table, 0, limit, get_obj(ctx, res), NULL, 0); - } - } - break; - case 'u' : - case 'U' : - switch (msg[3]) { - case 'f' : /* :suffix-search */ - case 'F' : - POP(car, args); - if (!BULKP(car)) { QLERR("string expected"); } - POP(res, args); - if (res == NIL) { - if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); } - } else if (!RECORDSP(res)) { - QLERR("records object expected"); - } - if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car), - GRN_OP_SUFFIX, get_obj(ctx, res), GRN_OP_OR) - < GRN_SUCCESS) { - QLERR("suffix search failed"); - } - break; - case 'b' : /* :subtract */ - case 'B' : - { - while (PAIRP(args)) { - POP(car, args); - if (!TABLEP(car)) { continue; } - grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_BUT); - } - } - break; - default : - res = F; - break; - } - break; - default : - res = F; - break; - } - break; - case 't' : - { - int n; - grn_id id = GRN_ID_NIL; - for (n = 0; (id = grn_table_next(ctx, table, id)); n++) ; - res = (n == grn_table_size(ctx, table)) ? T : F; - } - break; - case 'T' : - { - int n = 0; - grn_id id; - grn_table_cursor *c; - if ((c = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, - GRN_CURSOR_DESCENDING))) { - for (; (id = grn_table_cursor_next(ctx, c)); n++) ; - grn_table_cursor_close(ctx, c); - } - res = (n == grn_table_size(ctx, table)) ? T : F; - } - break; - case 'u' : /* :undef */ - case 'U' : - switch (msg[2]) { - case 'n' : - case 'N' : - switch (msg[3]) { - case 'd' : - case 'D' : - { - grn_obj *column; - POP(car, args); - if (obj2str(car, msg, &msg_size)) { return F; } - if (!(column = grn_obj_column(ctx, table, msg, msg_size))) { return F; } - if (!(msg_size = grn_obj_name(ctx, column, msg, STRBUF_SIZE))) { return F; } - res = grn_table_delete(ctx, ctx->impl->db, msg, msg_size) ? F : T; - } - break; - case 'i' : /* :union */ - case 'I' : - { - while (PAIRP(args)) { - POP(car, args); - if (!TABLEP(car)) { continue; } - grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_OR); - } - } - break; - default : - res = F; - break; - } - break; - default : - res = F; - break; - } - break; - case '+' : /* :+ (iterator next) */ - { - grn_id id; - POP(res, args); - if (res->header.type == GRN_CELL_OBJECT && - res->header.domain == DB_OBJ(table)->id && - (id = grn_table_next(ctx, table, res->u.o.id))) { - res->u.o.id = id; - } else { - res = F; - } - } - break; - case '\0' : /* : (iterator begin) */ - { - grn_id id; - id = grn_table_next(ctx, table, GRN_ID_NIL); - if (id == GRN_ID_NIL) { - res = F; - } else { - GRN_CELL_NEW(ctx, res); - obj_obj_bind(res, DB_OBJ(table)->id, id); - } - } - break; - } - break; - default : /* :columnname */ - res = table_column(ctx, base, msg, msg_size); - break; - } - if (load == 1) { - int i; - grn_cell *s, *saved; - struct _ins_stat *stat; - for (s = args, i = 0; PAIRP(s); s = CDR(s), i++) { - car = CAR(s); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - CAR(s) = table_column(ctx, base, msg, msg_size); - if (CAR(s) == F) { QLERR("invalid argument"); } - } - if (!(saved = grn_cell_alloc(ctx, sizeof(struct _ins_stat)))) { return F; } - stat = (struct _ins_stat *)saved->u.b.value; - stat->columns = args; - stat->ncolumns = i; - stat->nrecs = 0; - do { - GRN_QL_CO_WAIT(co, saved); - stat = (struct _ins_stat *)saved->u.b.value; - if (BULKP(args) && STRSIZE(args)) { - grn_cell *r, *o, obj, cons, dummy; - jctx jc; - jc.encoding = ctx->encoding; - jc.cur = args->u.b.value; - jc.str_end = args->u.b.value + args->u.b.size; - r = json_read(ctx, &jc, 0); - POP(car, r); - if (car == INTERN("@")) { /* hash */ - for (s = r; CAR(s) != INTERN("::key"); s = CDR(s)) { - if (!PAIRP(s)) { QLERR("invalid argument"); } - } - s = CADR(s); - o = grn_ql_table_add(ctx, table, s->u.b.value, s->u.b.size, &obj); - if (o != F) { - cons.header.type = GRN_CELL_LIST; - cons.header.impl_flags = 0; - cons.u.l.cdr = NIL; - while (PAIRP(r)) { - grn_obj *column; - POP(car, r); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - POP(car, r); - cons.u.l.car = car; - column = get_column(ctx, base, msg, msg_size, NULL); - column_value(ctx, column, obj.u.o.id, &cons, &dummy); - grn_obj_unlink(ctx, column); - } - stat->nrecs++; - } - } else { /* array */ - if (!BULKP(car)) { QLERR("invalid argument"); } - o = grn_ql_table_add(ctx, table, car->u.b.value, car->u.b.size, &obj); - - if (o != F) { - cons.header.type = GRN_CELL_LIST; - cons.header.impl_flags = 0; - cons.u.l.cdr = NIL; - for (s = stat->columns, i = 0; i < stat->ncolumns; s = CDR(s), i++) { - grn_obj *column; - POP(car, r); - cons.u.l.car = car; - column = grn_ctx_at(ctx, CAR(s)->u.o.id); - column_value(ctx, column, obj.u.o.id, &cons, &dummy); - } - stat->nrecs++; - } - } - } else { - co->mode |= GRN_CTX_TAIL; - } - { - grn_cell *_value = ctx->impl->value; - ctx->impl->value = saved; - grn_ctx_mgc(ctx); - ctx->impl->value = _value; - } - } while (!(co->mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))); - if ((res = grn_cell_new(ctx))) { - res->header.type = GRN_CELL_INT; - res->u.i.i = stat->nrecs; - } else { - res = F; - } - } else if (load == 2) { - int i; - grn_cell *s; - struct _ins_stat *stat; - for (s = args, i = 0; PAIRP(s); s = CDR(s), i++) { - car = CAR(s); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); } - CAR(s) = table_column(ctx, base, msg, msg_size); - if (CAR(s) == F) { QLERR("invalid argument"); } - } - if (!(s = grn_cell_alloc(ctx, sizeof(struct _ins_stat)))) { return F; } - stat = (struct _ins_stat *)s->u.b.value; // todo : not GC safe - stat->columns = args; - stat->ncolumns = i + 1; - stat->nrecs = 0; - do { - GRN_QL_CO_WAIT(co, stat); - if (BULKP(args) && STRSIZE(args)) { - const char *tokbuf[MAXCOLUMNS]; - grn_obj *column; - grn_cell val, obj, cons, dummy; - cons.header.type = GRN_CELL_LIST; - cons.header.impl_flags = 0; - cons.u.l.car = &val; - cons.u.l.cdr = NIL; - val.header.type = GRN_CELL_STR; - if (grn_str_tok(args->u.b.value, STRSIZE(args), '\t', tokbuf, MAXCOLUMNS, NULL) == stat->ncolumns) { - grn_cell *o; - if (grn_obj_lock(ctx, ctx->impl->db, GRN_ID_NIL, -1)) { - GRN_LOG(ctx, GRN_LOG_CRIT, "ha_table::load lock failed"); - } else { - o = grn_ql_table_add(ctx, table, args->u.b.value, - tokbuf[0] - args->u.b.value, &obj); - if (o != F) { - for (s = stat->columns, i = 1; i < stat->ncolumns; s = CDR(s), i++) { - val.u.b.value = (char *)tokbuf[i - 1] + 1; - val.u.b.size = tokbuf[i] - val.u.b.value; - unesc(ctx, &val); - column = grn_ctx_at(ctx, CAR(s)->u.o.id); - column_value(ctx, column, obj.u.o.id, &cons, &dummy); - } - stat->nrecs++; - } - grn_obj_unlock(ctx, ctx->impl->db, GRN_ID_NIL); - } - } - } else { - co->mode |= GRN_CTX_TAIL; - } - } while (!(co->mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))); - if ((res = grn_cell_new(ctx))) { - res->header.type = GRN_CELL_INT; - res->u.i.i = stat->nrecs; - } else { - res = F; - } - } - GRN_QL_CO_END(co); - return res; -} - -static grn_cell * -ha_object(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - char msg[STRBUF_SIZE]; - uint16_t msg_size; - grn_cell *obj, *car, *res; - if (!(obj = res = ctx->impl->code)) { QLERR("invalid receiver"); } - while (PAIRP(args)) { - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid message"); } - if (*msg == ':' && msg[1] == 'i') { - res = obj2oid(ctx, obj, NULL); - } else { - grn_obj *domain = grn_ctx_at(ctx, obj->header.domain); - grn_obj *column = grn_obj_column(ctx, domain, msg, msg_size); - if (!column) { - QLERR("invalid column %s", msg); - } - res = column_value(ctx, column, obj->u.o.id, args, NULL); - grn_obj_unlink(ctx, column); - POP(car, args); - } - } - return res; -} - -static grn_cell * -ha_query(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - /* args: (str1 @ bulk) (str2 @ bulk) .. */ - grn_rc rc; - grn_cell *x; - const char **strs; - grn_query *q; - unsigned int *str_lens; - int nstrs, found = 0, score = 0; - if (!PAIRP(args) || !BULKP(CAR(args))) { QLERR("invalid argument"); } - for (x = args, nstrs = 0; PAIRP(x) && BULKP(CAR(x)); x = CDR(x)) { nstrs++; } - if (!(strs = GRN_MALLOC(sizeof(intptr_t) * nstrs * 2))) { - QLERR("malloc failed"); - } - str_lens = (unsigned int *)&strs[nstrs]; - for (x = args, nstrs = 0; PAIRP(x) && BULKP(CAR(x)); x = CDR(x)) { - strs[nstrs] = STRVALUE(CAR(x)); - str_lens[nstrs] = STRSIZE(CAR(x)); - nstrs++; - } - q = (grn_query *)ctx->impl->code->u.p.value; - rc = grn_query_scan(ctx, q, strs, str_lens, nstrs, GRN_QUERY_SCAN_NORMALIZE, &found, &score); - GRN_FREE(strs); - if (rc) { QLERR("grn_query_scan failed"); } - if (!found) { return F; } - GRN_CELL_NEW(ctx, x); - SETINT(x, score); - return x; -} - -static grn_cell * -grn_obj_query(grn_ctx *ctx, const char *str, unsigned int str_len, - grn_operator default_op, int max_exprs, grn_encoding encoding) -{ - grn_query *q; - grn_cell *res = grn_cell_new(ctx); - if (!res || !(q = grn_query_open(ctx, str, str_len, default_op, max_exprs))) { - return NULL; - } - res->header.type = GRN_QUERY; - res->header.impl_flags = GRN_CELL_NATIVE|GRN_OBJ_ALLOCATED; - res->u.p.value = (grn_obj *)q; - res->u.p.func = ha_query; - return res; -} - -static void -uvector2str(grn_ctx *ctx, grn_obj *obj, grn_obj *buf) -{ - grn_obj *range = grn_ctx_at(ctx, obj->header.domain); - if (range && range->header.type == GRN_TYPE) { - // todo - } else { - grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); - if (v < ve) { - for (;;) { - grn_table_get_key2(ctx, range, *v, buf); - v++; - if (v < ve) { - GRN_TEXT_PUTC(ctx, buf, ' '); - } else { - break; - } - } - } - } -} - -static grn_cell * -ha_column(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - char msg[STRBUF_SIZE]; - uint16_t msg_size; - grn_id base; - grn_cell *car, *res; - grn_obj *column; - if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); } - base = ctx->impl->code->u.o.id; - if (!(column = grn_ctx_at(ctx, base))) { QLERR("grn_ctx_get failed"); } - POP(car, args); - if (obj2str(car, msg, &msg_size)) { QLERR("invalid message"); } - switch (*msg) { - case '\0' : - { - if (IDX_COLUMNP(ctx->impl->code)) { - grn_cell *q; - grn_operator op; - POP(q, args); - if (!QUERYP(q)) { - if (!BULKP(q)) { return F; } - if (!(q = grn_obj_query(ctx, q->u.b.value, q->u.b.size, GRN_OP_AND, 32, ctx->encoding))) { - QLERR("query_obj_new failed"); - } - } - /* TODO: specify record unit */ - /* (idxcolumn query ((column1 weight1) (column2 weight2) ...) records operator+ */ - POP(car, args); - /* TODO: handle weights */ - POP(res, args); - if (RECORDSP(res)) { - char ops[STRBUF_SIZE]; - uint16_t ops_size; - op = GRN_OP_AND; - POP(car, args); - if (!obj2str(car, ops, &ops_size)) { - switch (*ops) { - case '+': op = GRN_OP_OR; break; - case '-': op = GRN_OP_BUT; break; - case '*': op = GRN_OP_AND; break; - case '>': op = GRN_OP_ADJUST; break; - } - } - } else { - grn_obj *table; - if (!(table = grn_ctx_at(ctx, DB_OBJ(column)->range))) { return F; } - res = rec_obj_new(ctx, table, NULL); - if (ERRP(ctx, GRN_WARN)) { return F; } - op = GRN_OP_OR; - } - grn_obj_search(ctx, column, (grn_obj *)q->u.p.value, RVALUE(res), op, NULL); - } else { - char name[STRBUF_SIZE]; - uint16_t name_size; - grn_obj *table; - POP(car, args); - if (obj2str(car, name, &name_size)) { return F; } - if (!(table = grn_column_table(ctx, column))) { return F; } - res = grn_ql_table_get(ctx, table, name, name_size, NULL); - if (res != F) { - // grn_obj_lock(ctx, ctx->impl->db, GRN_ID_NIL, -1)) - column_value(ctx, column, res->u.o.id, args, res); - // grn_obj_unlock(ctx, ctx->impl->db, GRN_ID_NIL); - } - } - } - break; - case ':' : - switch (msg[1]) { - case 's' : /* :schema */ - case 'S' : - { - switch (column->header.type) { - case GRN_COLUMN_FIX_SIZE : - case GRN_COLUMN_VAR_SIZE : - res = CONS(get_cell(ctx, grn_ctx_at(ctx, DB_OBJ(column)->range)), NIL); - break; - case GRN_COLUMN_INDEX : - { - /* todo : - grn_db_trigger *t; - res = CONS(INTERN("::match"), CONS(NIL, NIL)); - for (t = column->triggers; t; t = t->next) { - if (t->type == grn_db_index_target) { - res = CONS(get_cell(ctx, grn_ctx_at(ctx, t->target)), res); - } - } - */ - res = CONS(INTERN(":index"), CONS(CONS(INTERN("quote"), CONS(res, NIL)), NIL)); - } - break; - case GRN_CELL_PSEUDO_COLUMN : - QLERR("not supported yet"); - break; - default : - QLERR("invalid column type"); - break; - } - /* - { - char *p, buf[GRN_PAT_MAX_KEY_SIZE]; - strcpy(buf, _grn_pat_key(ctx, ctx->impl->db->keys, base)); - if (!(p = strchr(buf, '.'))) { QLERR("invalid columnname %s", buf); } - *p = ':'; - res = CONS(INTERN("::def"), CONS(INTERN(p), res)); - *p = '\0'; - res = CONS(INTERN(buf), res); - } - */ - } - break; - } - break; - } - return res; -} - -void -grn_ql_obj_bind(grn_obj *obj, grn_cell *symbol) -{ - symbol->header.type = obj->header.type; - symbol->header.impl_flags |= GRN_CELL_NATIVE; - symbol->u.o.id = DB_OBJ(obj)->id; - symbol->header.domain = DB_OBJ(obj)->header.domain; - switch (symbol->header.type) { - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_NO_KEY : - symbol->u.o.func = ha_table; - break; - case GRN_COLUMN_FIX_SIZE : - symbol->u.o.func = ha_column; - break; - case GRN_COLUMN_VAR_SIZE : - symbol->u.o.func = ha_column; - break; - case GRN_COLUMN_INDEX : - symbol->u.o.func = ha_column; - break; - default : - symbol->u.o.func = ha_void; - break; - } -} - -#define PVALUE(obj,type) ((type *)((obj)->u.p.value)) - -inline static void -snip_obj_bind(grn_cell *obj, grn_snip *snip) -{ - obj->header.type = GRN_SNIP; - obj->header.impl_flags = GRN_CELL_NATIVE|GRN_OBJ_ALLOCATED; - obj->u.p.value = (grn_obj *)snip; - obj->u.p.func = ha_snip; -} - -struct _patsnip_spec { - grn_obj *table; - int width; - int max_results; - column_exp *ce; -}; - -void -grn_obj_patsnip_spec_close(grn_ctx *ctx, patsnip_spec *spec) -{ - if (spec) { - column_exp_close(ctx, spec->ce); - GRN_FREE(spec); - } -} - -static grn_cell * -ha_snip(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - /* args: (str @ bulk) */ - if (!PAIRP(args) || !BULKP(CAR(args))) { QLERR("invalid argument"); } - switch (ctx->impl->code->header.type) { - case GRN_SNIP : - { - grn_obj buf; - unsigned int i, len, max_len, nresults; - grn_snip *s = PVALUE(ctx->impl->code, grn_snip); - grn_cell *v, *str = CAR(args), *spc = PAIRP(CDR(args)) ? CADR(args) : NIL; - if ((grn_snip_exec(ctx, s, str->u.b.value, str->u.b.size, &nresults, &max_len))) { - QLERR("grn_snip_exec failed"); - } - GRN_TEXT_INIT(&buf, 0); - if (grn_bulk_resize(ctx, &buf, max_len)) { QLERR("grn_bulk_resize failed"); } - - if (nresults) { - for (i = 0; i < nresults; i++) { - if (i && spc != NIL) { grn_obj_inspect(ctx, spc, &buf, 0); } - if (grn_bulk_reserve(ctx, &buf, max_len)) { - grn_bulk_fin(ctx, &buf); - QLERR("grn_bulk_space failed"); - } - if ((grn_snip_get_result(ctx, s, i, buf.u.b.curr, &len))) { - grn_bulk_fin(ctx, &buf); - QLERR("grn_snip_get_result failed"); - } - buf.u.b.curr += len; - } - } else { - char *ss = str->u.b.value, *se = str->u.b.value + str->u.b.size; - if (grn_substring(ctx, &ss, &se, 0, s->width, ctx->encoding)) { - QLERR("grn_substring failed"); - } - grn_bulk_write(ctx, &buf, ss, se - ss); - } - GRN_STR2OBJ(ctx, &buf, v); - return v; - } - break; - case GRN_PATSNIP : - { - grn_obj buf; - patsnip_spec *spec = PVALUE(ctx->impl->code, patsnip_spec); - off_t off = 0; - const char *rest; - grn_pat_scan_hit sh[1024]; - grn_cell *v, *expr, *str = CAR(args); - char *string = STRVALUE(str); - size_t len = STRSIZE(str); - GRN_TEXT_INIT(&buf, 0); - if (grn_bulk_resize(ctx, &buf, len)) { QLERR("grn_bulk_resize failed."); } - while (off < len) { - grn_obj *table = spec->table; - int i, nhits = grn_pat_scan(ctx, (grn_pat *)table, string + off, len - off, - sh, 1024, &rest); - for (i = 0, off = 0; i < nhits; i++) { - if (sh[i].offset < off) { continue; } /* skip overlapping region. */ - grn_bulk_write(ctx, &buf, string + off, sh[i].offset - off); - column_exp_exec(ctx, spec->ce, sh[i].id); - expr = spec->ce->expr; - // expr = grn_ql_eval(ctx, spec->ce->expr, NIL); - POP(v, expr); - grn_obj_inspect(ctx, grn_ql_eval(ctx, v, NIL), &buf, 0); - grn_bulk_write(ctx, &buf, string + sh[i].offset, sh[i].length); - POP(v, expr); - grn_obj_inspect(ctx, grn_ql_eval(ctx, v, NIL), &buf, 0); - off = sh[i].offset + sh[i].length; - } - if (string + off < rest) { - grn_bulk_write(ctx, &buf, string + off, rest - (string + off)); - } - off = rest - string; - } - GRN_STR2OBJ(ctx, &buf, v); - return v; - } - break; - default : - QLERR("snip failed. invalid expr"); - } -} - -static void disp_j(grn_ctx *ctx, grn_cell *obj, grn_obj *buf); - -static void -disp_j_with_format(grn_ctx *ctx, grn_cell *args, grn_obj *buf) -{ - grn_cell *car; - POP(car, args); - switch (car->header.type) { - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_NO_KEY : - { - grn_id id, base; - grn_cell *columns; - int i, offset = 0, limit = 10, flags = GRN_CURSOR_ASCENDING; - grn_obj *r = RVALUE(car); - column_exp *ce; - base = car->u.o.id; - POP(columns, args); - if (!PAIRP(columns)) { - disp_j(ctx, car, buf); - return; - } - if ((ce = column_exp_open(ctx, r, columns, NIL))) { - POP(car, args); - if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; } - POP(car, args); - if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; } - if (limit <= 0) { limit += grn_table_size(ctx, r); } - POP(car, args); - { - char msg[STRBUF_SIZE]; - uint16_t msg_size; - if (!obj2str(car, msg, &msg_size) && (*msg == 'd')) { - flags |= GRN_CURSOR_DESCENDING; - } - } - { - grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, offset, - offset + limit, flags); - GRN_TEXT_PUTC(ctx, buf, '['); - for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) { - if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); } - column_exp_exec(ctx, ce, id); - disp_j(ctx, ce->expr, buf); - } - GRN_TEXT_PUTC(ctx, buf, ']'); - grn_table_cursor_close(ctx, tc); - } - column_exp_close(ctx, ce); - } - } - break; - case GRN_UVECTOR : - { - column_exp *ce; - grn_cell *parameter, *columns; - grn_obj *u = car->u.p.value, *r = grn_ctx_at(ctx, u->header.domain); - POP(parameter, args); - POP(columns, args); - if (!PAIRP(columns)) { - disp_j(ctx, car, buf); - return; - } - if ((ce = column_exp_open(ctx, r, columns, parameter))) { - /* - POP(car, args); - if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; } - POP(car, args); - if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; } - */ - { - int i; - grn_id *v = (grn_id *)GRN_BULK_HEAD(u), *ve = (grn_id *)GRN_BULK_CURR(u); - GRN_TEXT_PUTC(ctx, buf, '['); - for (i = 0; v < ve; v++, i++) { - if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); } - column_exp_exec(ctx, ce, *v); - disp_j(ctx, ce->expr, buf); - } - GRN_TEXT_PUTC(ctx, buf, ']'); - } - column_exp_close(ctx, ce); - } - } - break; - case GRN_CELL_OBJECT : - { - grn_cell *columns; - column_exp *ce; - grn_obj *r = get_domain(ctx, car); - POP(columns, args); - if (!PAIRP(columns)) { - disp_j(ctx, car, buf); - return; - } - if ((ce = column_exp_open(ctx, r, columns, NIL))) { - column_exp_exec(ctx, ce, car->u.o.id); - disp_j(ctx, ce->expr, buf); - column_exp_close(ctx, ce); - } - } - break; - default : - disp_j(ctx, car, buf); - if (ERRP(ctx, GRN_WARN)) { return; } - break; - } -} - -static void -disp_j(grn_ctx *ctx, grn_cell *obj, grn_obj *buf) -{ - if (!obj || obj == NIL) { - GRN_TEXT_PUTS(ctx, buf, "[]"); - } else if (obj == T) { - GRN_TEXT_PUTS(ctx, buf, "true"); - } else if (obj == F) { - GRN_TEXT_PUTS(ctx, buf, "false"); - } else { - switch (obj->header.type) { - case GRN_VOID : - if (SYMBOLP(obj) && obj != INTERN("null")) { - uint16_t size = 0; - const char *r = _grn_hash_strkey_by_val(obj, &size); - if (size && (*r == ':')) { - r++; - size--; - } - grn_text_esc(ctx, buf, r, size); - } else { - GRN_TEXT_PUTS(ctx, buf, "null"); - } - break; - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_NO_KEY : - { - int i; - grn_id id; - grn_cell o; - grn_obj *r = RVALUE(obj); - { - grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, 0, 0, - GRN_CURSOR_ASCENDING); - GRN_TEXT_PUTC(ctx, buf, '['); - for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) { - if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); } - obj_obj_bind(&o, obj->u.o.id, id); - disp_j(ctx, &o, buf); - if (ERRP(ctx, GRN_WARN)) { return; } - } - GRN_TEXT_PUTC(ctx, buf, ']'); - grn_table_cursor_close(ctx, tc); - } - } - break; - case GRN_CELL_LIST : - if (CAR(obj) == INTERN(":")) { - disp_j_with_format(ctx, CDR(obj), buf); - if (ERRP(ctx, GRN_WARN)) { return; } - } else if (CAR(obj) == INTERN("@")) { - int o; - GRN_TEXT_PUTC(ctx, buf, '{'); - for (obj = CDR(obj), o = 0;; o = 1 - o) { - if (PAIRP(obj)) { - disp_j(ctx, CAR(obj), buf); - if (ERRP(ctx, GRN_WARN)) { return; } - } - if ((obj = CDR(obj)) && (obj != NIL)) { - if (PAIRP(obj)) { - GRN_TEXT_PUTS(ctx, buf, o ? ", " : ": "); - } else { - GRN_TEXT_PUTS(ctx, buf, " . "); - disp_j(ctx, obj, buf); - if (ERRP(ctx, GRN_WARN)) { return; } - GRN_TEXT_PUTC(ctx, buf, '}'); - break; - } - } else { - GRN_TEXT_PUTC(ctx, buf, '}'); - break; - } - } - } else { - GRN_TEXT_PUTC(ctx, buf, '['); - for (;;) { - disp_j(ctx, CAR(obj), buf); - if (ERRP(ctx, GRN_WARN)) { return; } - if ((obj = CDR(obj)) && (obj != NIL)) { - if (PAIRP(obj)) { - GRN_TEXT_PUTS(ctx, buf, ", "); - } else { - GRN_TEXT_PUTS(ctx, buf, " . "); - disp_j(ctx, obj, buf); - if (ERRP(ctx, GRN_WARN)) { return; } - GRN_TEXT_PUTC(ctx, buf, ']'); - break; - } - } else { - GRN_TEXT_PUTC(ctx, buf, ']'); - break; - } - } - } - break; - case GRN_CELL_OBJECT : - { - grn_obj key; - GRN_TEXT_INIT(&key, 0); - grn_ql_obj_key(ctx, obj, &key); - grn_text_esc(ctx, buf, GRN_BULK_HEAD(&key), GRN_BULK_VSIZE(&key)); - grn_obj_close(ctx, &key); - } - break; - case GRN_CELL_TIME : - { - double dv= obj->u.tv.tv_sec; - dv += obj->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F; - grn_text_ftoa(ctx, buf, dv); - } - break; - case GRN_UVECTOR : - { - grn_obj tmp; - GRN_TEXT_INIT(&tmp, 0); - uvector2str(ctx, obj->u.p.value, &tmp); - grn_text_esc(ctx, buf, GRN_BULK_HEAD(&tmp), GRN_BULK_VSIZE(&tmp)); - grn_obj_close(ctx, &tmp); - } - break; - default : - grn_obj_inspect(ctx, obj, buf, GRN_OBJ_INSPECT_ESC|GRN_OBJ_INSPECT_SYMBOL_AS_STR); - break; - } - } -} - -static void disp_t(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int *f); - -static void -disp_t_with_format(grn_ctx *ctx, grn_cell *args, grn_obj *buf, int *f) -{ - grn_cell *car; - POP(car, args); - switch (car->header.type) { - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_NO_KEY : - { - grn_id id, base; - grn_cell *columns; - int i, offset = 0, limit = 10, flags = GRN_CURSOR_ASCENDING; - grn_obj *r = RVALUE(car); - column_exp *ce; - base = car->u.o.id; - POP(columns, args); - if (!PAIRP(columns)) { - disp_t(ctx, car, buf, f); - return; - } - if ((ce = column_exp_open(ctx, r, columns, NIL))) { - POP(car, args); - if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; } - POP(car, args); - if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; } - if (limit <= 0) { limit += grn_table_size(ctx, r); } - POP(car, args); - { - char msg[STRBUF_SIZE]; - uint16_t msg_size; - if (!obj2str(car, msg, &msg_size) && (*msg == 'd')) { - flags |= GRN_CURSOR_DESCENDING; - } - } - { - grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, offset, - offset + limit, flags); - for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) { - if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; } - column_exp_exec(ctx, ce, id); - disp_t(ctx, ce->expr, buf, f); - } - grn_table_cursor_close(ctx, tc); - } - column_exp_close(ctx, ce); - } - } - break; - case GRN_CELL_OBJECT : - { - grn_cell *columns; - column_exp *ce; - grn_obj *r = get_domain(ctx, car); - POP(columns, args); - if (!PAIRP(columns)) { - disp_t(ctx, car, buf, f); - return; - } - if ((ce = column_exp_open(ctx, r, columns, NIL))) { - column_exp_exec(ctx, ce, car->u.o.id); - disp_t(ctx, ce->expr, buf, f); - column_exp_close(ctx, ce); - } - } - break; - default : - disp_t(ctx, car, buf, f); - break; - } -} - -inline static void -bulk_tsv_esc(grn_ctx *ctx, grn_obj *buf, const char *s, int len) -{ - const char *e; - unsigned int l; - for (e = s + len; s < e; s += l) { - if (!(l = grn_charlen(ctx, s, e))) { break; } - if (l == 1) { - switch (*s) { - case '\t' : - grn_bulk_write(ctx, buf, "\\t", 2); - break; -#ifdef GRN_QL_ESCAPE_NEWLINE - case '\n' : - grn_bulk_write(ctx, buf, "\\n", 2); - break; - case '\r' : - grn_bulk_write(ctx, buf, "\\r", 2); - break; -#endif /* GRN_QL_ESCAPE_NEWLINE */ - case '\\' : - grn_bulk_write(ctx, buf, "\\\\", 2); - break; - default : - GRN_TEXT_PUTC(ctx, buf, *s); - } - } else { - grn_bulk_write(ctx, buf, s, l); - } - } -} - -static void -disp_t(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int *f) -{ - if (!obj || obj == NIL) { - GRN_TEXT_PUTS(ctx, buf, "()"); *f = 1; - } else if (obj == T) { - GRN_TEXT_PUTS(ctx, buf, "#t"); *f = 1; - } else if (obj == F) { - GRN_TEXT_PUTS(ctx, buf, "#f"); *f = 1; - } else { - switch (obj->header.type) { - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_NO_KEY : - { - int i; - grn_id id; - grn_cell o; - grn_obj *r = RVALUE(obj); - grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, 0, 0, - GRN_CURSOR_ASCENDING); - for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) { - obj_obj_bind(&o, obj->u.o.id, id); - if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; } - disp_t(ctx, &o, buf, f); - } - grn_table_cursor_close(ctx, tc); - } - break; - case GRN_CELL_LIST : - if (CAR(obj) == INTERN(":")) { - disp_t_with_format(ctx, CDR(obj), buf, f); - } else if (CAR(obj) == INTERN("@")) { - int o0, o; - grn_cell *val = CDR(obj); - for (o0 = 0; o0 <= 1; o0++) { - if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; } - for (obj = val, o = o0;; o = 1 - o) { - if (!o) { disp_t(ctx, CAR(obj), buf, f); } - if ((obj = CDR(obj)) && (obj != NIL)) { - if (PAIRP(obj)) { - if (!o && PAIRP(CDR(obj))) { GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; } - } else { - if (!o) { - GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; /* dot pair */ - disp_t(ctx, obj, buf, f); - } - break; - } - } else { - break; - } - } - } - } else { - grn_cell *car; - for (;;) { - POP(car, obj); - if (PAIRP(car)) { - car = grn_ql_eval(ctx, car, NIL); - } - disp_t(ctx, car, buf, f); - if ((obj != NIL)) { - if (PAIRP(obj)) { - GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; - } else { - GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; /* dot pair */ - disp_t(ctx, obj, buf, f); - break; - } - } else { - break; - } - } - } - break; - case GRN_CELL_STR : - bulk_tsv_esc(ctx, buf, obj->u.b.value, obj->u.b.size); - *f = 1; - break; - case GRN_CELL_TIME : - { - double dv= obj->u.tv.tv_sec; - dv += obj->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F; - grn_text_ftoa(ctx, buf, dv); - *f = 1; - } - break; - case GRN_UVECTOR : - uvector2str(ctx, obj->u.p.value, buf); - break; - default : - grn_obj_inspect(ctx, obj, buf, 0); *f = 1; - break; - } - } -} - -inline static grn_cell * -mk_atom(grn_ctx *ctx, char *str, unsigned int len) -{ - const char *cur, *str_end = str + len; - int64_t ivalue = grn_atoll(str, str_end, &cur); - if (cur == str_end) { - grn_cell *x; - GRN_CELL_NEW(ctx, x); - SETINT(x, ivalue); - return x; - } - switch (*str) { - case 't' : - if (len == 4 && !memcmp(str, "true", 4)) { return T; } - break; - case 'f' : - if (len == 5 && !memcmp(str, "false", 5)) { return F; } - break; - /* - case 'n' : - if (len == 4 && !memcmp(str, "null", 4)) { return NIL; } - break; - */ - } - if (0 < len && len < GRN_PAT_MAX_KEY_SIZE - 1) { - char buf[GRN_PAT_MAX_KEY_SIZE]; - memcpy(buf, str, len); - buf[len] = '\0'; - return INTERN(buf); - } else { - return F; - } -} - -inline static grn_cell * -json_readstr(grn_ctx *ctx, jctx *jc) -{ - char *start, *end; - for (start = end = jc->cur;;) { - unsigned int len; - /* null check and length check */ - if (!(len = grn_charlen(ctx, end, jc->str_end))) { - jc->cur = jc->str_end; - break; - } - if (grn_isspace(end, jc->encoding) - || *end == ':' || *end == ',' - || *end == '[' || *end == '{' - || *end == ']' || *end == '}') { - jc->cur = end; - break; - } - end += len; - } - if (start < end || jc->cur < jc->str_end) { - return mk_atom(ctx, start, end - start); - } else { - return F; - } -} - -inline static grn_cell * -json_readstrexp(grn_ctx *ctx, jctx *jc, int keyp) -{ - grn_cell *res; - char *start, *src, *dest; - for (start = src = dest = jc->cur;;) { - unsigned int len; - /* null check and length check */ - if (!(len = grn_charlen(ctx, src, jc->str_end))) { - jc->cur = jc->str_end; - if (start < dest) { - res = keyp - ? grn_ql_mk_symbol2(ctx, start, dest - start, 1) - : grn_ql_mk_string(ctx, start, dest - start); - return res ? res : F; - } - return F; - } - if (src[0] == '"' && len == 1) { - jc->cur = src + 1; - res = keyp - ? grn_ql_mk_symbol2(ctx, start, dest - start, 1) - : grn_ql_mk_string(ctx, start, dest - start); - return res ? res : F; - } else if (src[0] == '\\' && src + 1 < jc->str_end && len == 1) { - src++; - *dest++ = *src++; - } else { - while (len--) { *dest++ = *src++; } - } - } -} - -static grn_cell * -json_read(grn_ctx *ctx, jctx *jc, int keyp) -{ - for (;;) { - SKIPSPACE(jc); - if (jc->cur >= jc->str_end) { return NULL; } - switch (*jc->cur) { - case '[': - jc->cur++; - { - grn_cell *o, *r = NIL, **p = &r; - while ((o = json_read(ctx, jc, 0)) && o != F) { - *p = CONS(o, NIL); - if (ERRP(ctx, GRN_WARN)) { return F; } - p = &CDR(*p); - } - return r; - } - case '{': - jc->cur++; - { - grn_cell *o, *r = CONS(INTERN("@"), NIL), **p = &(CDR(r)); - int i = 0; - while ((o = json_read(ctx, jc, ((++i)&1))) && o != F) { - *p = CONS(o, NIL); - if (ERRP(ctx, GRN_WARN)) { return F; } - p = &CDR(*p); - } - return r; - } - case '}': - case ']': - jc->cur++; - return NULL; - case ',': - jc->cur++; - break; - case ':': - jc->cur++; - break; - case '"': - jc->cur++; - return json_readstrexp(ctx, jc, keyp); - default: - return json_readstr(ctx, jc); - } - } -} Deleted: lib/ql.h (+0 -433) 100644 =================================================================== --- lib/ql.h 2012-02-03 11:43:41 +0900 (b7e1bb6) +++ /dev/null @@ -1,433 +0,0 @@ -/* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009 Brazil - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef GRN_QL_H -#define GRN_QL_H - -#ifndef GRN_STORE_H -#include "store.h" -#endif /* GRN_STORE_H */ - -#ifndef GRN_COM_H -#include "com.h" -#endif /* GRN_COM_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef _ISOC99_SOURCE -#define _ISOC99_SOURCE -#endif /* _ISOC99_SOURCE */ -#if WIN32 -#define _USE_MATH_DEFINES -#endif /* WIN32 */ - -#include <math.h> - -#ifdef HAVE_MESSAGE_PACK -#include <msgpack.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/**** grn_expr ****/ - -#define GRN_EXPR_MISSING_NAME "expr_missing" - -/**** grn_cell ****/ - -/* flag values used for grn_cell.header.impl_flags */ -/* bit 0~2 are reserved */ -#define GRN_CELL_SYMBOL (1L<<3) /* ql: registered in the symbol table */ -#define GRN_CELL_PROMISE (1L<<4) /* ql: promise object */ -#define GRN_CELL_NATIVE (1L<<5) /* ql: native function */ -#define GRN_CELL_MARKED (1L<<6) /* ql: used in garbage collection */ -#define GRN_CELL_MARK2 (1L<<7) /* ql: used in callback function */ - -/* type values used for grn_cell.header.type */ -#define GRN_CELL_INT (0x70) -#define GRN_CELL_FLOAT (0x71) -#define GRN_CELL_STR (0x72) -#define GRN_CELL_OP (0x73) -#define GRN_CELL_OBJECT (0x74) -#define GRN_CELL_PROC (0x75) -#define GRN_CELL_SYNTAX (0x76) -#define GRN_CELL_TIME (0x77) -#define GRN_CELL_PSEUDO_COLUMN (0x78) -#define GRN_CELL_LIST (0x80) -#define GRN_CELL_CLOSURE (0x81) -#define GRN_CELL_MACRO (0x82) -#define GRN_CELL_CONTINUATION (0x83) - -typedef struct _grn_ql_co grn_ql_co; -typedef struct _grn_cell grn_cell; -typedef grn_cell *grn_ql_native_func(grn_ctx *, grn_cell *, grn_ql_co *); -typedef struct _grn_tmp_db_obj grn_tmp_db_obj; - -struct _grn_cell { - grn_obj_header header; - union { - struct { - grn_id id; - grn_ql_native_func *func; - } o; - struct { - grn_obj *value; - grn_ql_native_func *func; - } p; - struct { - char *value; - uint32_t size; - } b; - struct { - grn_cell *car; - grn_cell *cdr; - } l; - struct { - int64_t i; - } i; - struct { - double d; - } d; - struct { - int8_t op; - int8_t mode; - int16_t weight; - int32_t option; - } op; - grn_timeval tv; - } u; -}; - -struct _grn_ql_co { - uint16_t mode; - uint16_t last; - grn_ql_native_func *func; - void *data; -}; - -struct _grn_tmp_db_obj { - grn_db_obj *obj; - grn_cell cell; -}; - -grn_cell *grn_get(const char *key); -grn_cell *grn_at(const char *key); -grn_rc grn_del(const char *key); - -/**** grn_ctx_impl ****/ - -typedef enum { - GRN_LOADER_BEGIN = 0, - GRN_LOADER_TOKEN, - GRN_LOADER_STRING, - GRN_LOADER_SYMBOL, - GRN_LOADER_NUMBER, - GRN_LOADER_STRING_ESC, - GRN_LOADER_UNICODE0, - GRN_LOADER_UNICODE1, - GRN_LOADER_UNICODE2, - GRN_LOADER_UNICODE3, - GRN_LOADER_END -} grn_loader_stat; - -typedef struct { - grn_obj values; - grn_obj level; - grn_obj columns; - int32_t key_offset; - grn_obj *table; - grn_obj *last; - grn_obj *ifexists; - grn_obj *each; - uint32_t unichar; - uint32_t values_size; - uint32_t nrecords; - grn_loader_stat stat; - grn_content_type input_type; -} grn_loader; - -#define GRN_STACK_SIZE 1024 -#define GRN_CTX_N_SEGMENTS 512 - -#ifdef ENABLE_MEMORY_DEBUG -typedef struct _grn_alloc_info grn_alloc_info; -struct _grn_alloc_info -{ - void *address; - int freed; - char alloc_backtrace[4096]; - char free_backtrace[4096]; - grn_alloc_info *next; -}; -#endif - -struct _grn_ctx_impl { - grn_encoding encoding; - - /* memory pool portion */ - int32_t lifoseg; - int32_t currseg; - grn_critical_section lock; - grn_io_mapinfo segs[GRN_CTX_N_SEGMENTS]; - -#ifdef USE_DYNAMIC_MALLOC_CHANGE - /* memory allocation portion */ - grn_malloc_func malloc_func; - grn_calloc_func calloc_func; - grn_realloc_func realloc_func; - grn_strdup_func strdup_func; -#endif - -#ifdef ENABLE_MEMORY_DEBUG - /* memory debug portion */ - grn_alloc_info *alloc_info; -#endif - - /* qe portion */ - grn_obj *stack[GRN_STACK_SIZE]; - uint32_t stack_curr; - grn_hash *expr_vars; - grn_obj *curr_expr; - grn_obj *qe_next; - void *parser; - grn_timeval tv; - - /* loader portion */ - grn_edge *edge; - grn_loader loader; - - /* plugin portion */ - const char *plugin_path; - - /* output portion */ - grn_content_type output_type; - const char *mime_type; - grn_obj names; - grn_obj levels; - - /* command portion */ - grn_command_version command_version; - - /* match escalation portion */ - int64_t match_escalation_threshold; - - /* lifetime portion */ - grn_proc_func *finalizer; - - /* ql portion */ - uint32_t ncells; - uint32_t seqno; - uint32_t lseqno; - uint32_t nbinds; - uint32_t nunbinds; - uint8_t feed_mode; - uint8_t batchmode; - uint8_t gc_verbose; - uint8_t op; - int tok; - char *cur; - char *str_end; - grn_cell **pht; /* tail of placeholders */ - grn_cell arg; /* wait_data container (for coroutine) */ - grn_obj *db; - uint32_t n_entries; - grn_array *objects; /* objects */ - grn_array *values; /* temporary objects */ - grn_hash *symbols; /* symbol table */ - grn_cell *phs; /* list of placeholders */ - grn_ql_co co; /* coroutine info */ - grn_cell *args; /* register for arguments of function */ - grn_cell *envir; /* stack register for current environment */ - grn_cell *code; /* register for current code */ - grn_cell *dump; /* stack register for next evaluation */ - grn_cell *value; /* evaluated value */ - grn_cell *global_env; /* global variables */ - char *inbuf; - grn_obj *outbuf; - grn_obj subbuf; - unsigned int bufcur; - void (*output)(grn_ctx *, int, void *); - grn_com *com; - unsigned int com_status; - union { - void *ptr; - int fd; - uint32_t u32; - uint64_t u64; - } data; - -#ifdef HAVE_MESSAGE_PACK - msgpack_packer msgpacker; -#endif -}; - -/**** query language ****/ - -#define GRN_QL_CO_BEGIN(c) if (c) { switch((c)->last) { case 0: -#define GRN_QL_CO_WAIT(c,d) \ - (c)->last = __LINE__; (c)->data = (d); return NULL;\ - case __LINE__: (d) = (c)->data; -#define GRN_QL_CO_END(c) (c)->last = 0; }} - -#define GRN_QL_PLACEHOLDER_CHAR '?' - -#define GRN_QL_SET_MODE(c,m) ((c)->impl->feed_mode = (m)) -#define GRN_QL_GET_MODE(c) ((c)->impl->feed_mode) -#define GRN_QL_GET_STAT(c) ((c)->stat) - -enum { - grn_ql_atonce = 0, - grn_ql_step -}; - -#define GRN_QL_TOPLEVEL 0x00 -#define GRN_CTX_QUITTING 0x0f -#define GRN_QL_EVAL 0x40 -#define GRN_QL_NATIVE 0x41 -#define GRN_QL_WAIT_EXPR 0xc0 -#define GRN_QL_WAIT_ARG 0xc1 -#define GRN_QL_WAIT_DATA 0xc2 - -#define GRN_QL_WAITINGP(c) ((c)->stat & 0x80) - -extern grn_cell *grn_ql_nil; /* special cell representing empty cell */ -extern grn_cell *grn_ql_t; /* special cell representing #t */ -extern grn_cell *grn_ql_f; /* special cell representing #f */ - -#define NIL grn_ql_nil -#define T grn_ql_t -#define F grn_ql_f - -void grn_ql_init_globals(grn_ctx *c); - -grn_cell *grn_ql_at(grn_ctx *c, const char *key); -grn_rc grn_ql_def_db_funcs(grn_ctx *c); - -#define GRN_OBJ_INSPECT_ESC 1 -#define GRN_OBJ_INSPECT_SYMBOL_AS_STR 2 - -void grn_obj_inspect(grn_ctx *c, grn_cell *obj, grn_obj *buf, int flags); -grn_cell *grn_ql_def_native_func(grn_ctx *c, const char *name, grn_ql_native_func *func); -grn_cell *grn_ql_feed(grn_ctx *c, char *str, uint32_t str_size, int mode); -grn_cell *grn_ql_eval(grn_ctx *c, grn_cell *code, grn_cell *objs); -grn_rc grn_obj2int(grn_ctx *c, grn_cell *o); - -const char *_grn_ql_obj_key(grn_ctx *c, grn_cell *obj, uint32_t *key_size); -grn_obj *grn_ql_obj_key(grn_ctx *ctx, grn_cell *obj, grn_obj *value); -grn_cell *grn_ql_mk_symbol(grn_ctx *ctx, const char *name, int name_size); -grn_cell *grn_ql_obj_new(grn_ctx *c, grn_id domain, grn_id self); -void grn_ql_obj_bind(grn_obj *obj, grn_cell *symbol); - -grn_cell *grn_ql_mk_string(grn_ctx *c, const char *str, unsigned int len); -grn_cell *grn_ql_mk_symbol2(grn_ctx *ctx, const char *q, unsigned int len, int kwdp); - -grn_cell *grn_cell_new(grn_ctx *c); -grn_cell *grn_cell_alloc(grn_ctx *c, uint32_t size); -void grn_cell_clear(grn_ctx *c, grn_cell *o); -grn_cell *grn_cell_cons(grn_ctx *ctx, grn_cell *a, grn_cell *b); -void grn_ql_init_const(void); - -grn_rc grn_ql_obj_mark(grn_ctx *ctx, grn_cell *o); -grn_rc grn_ql_obj_unmark(grn_ctx *ctx, grn_cell *o); - -grn_rc grn_ctx_mgc(grn_ctx *ctx); - -typedef struct _patsnip_spec patsnip_spec; -void grn_obj_patsnip_spec_close(grn_ctx *ctx, patsnip_spec *ss); - -#define GRN_OBJ2VALUE(o,v,s) ((v) = (o)->u.b.value, (s) = (o)->u.b.size) -#define GRN_VALUE2OBJ(o,v,s) ((o)->u.b.value = (v), (o)->u.b.size = (s)) - -#define VOIDP(c) ((c) == NIL || !(c) || (c)->header.type == GRN_VOID) -#define OBJECTP(c) ((c)->header.type == GRN_CELL_OBJECT) -#define RECORDSP(c) ((c)->header.type == GRN_TABLE_HASH_KEY) -#define SNIPP(c) ((c)->header.type == GRN_SNIP) -#define BULKP(c) ((c)->header.type == GRN_CELL_STR) -#define PAIRP(c) (((c)->header.type == GRN_CELL_LIST)) -#define LISTP(c) (PAIRP(c) || (c) == NIL) -#define INTP(c) ((c)->header.type == GRN_CELL_INT) -#define TABLEP(c) (GRN_TABLE_HASH_KEY <= (c)->header.type && (c)->header.type <= GRN_DB) -#define RAW_TABLEP(c) ((c)->header.type == GRN_TYPE) -#define NATIVE_FUNCP(c) ((c)->header.impl_flags & GRN_CELL_NATIVE) -#define QUERYP(c) ((c)->header.type == GRN_QUERY) -#define RA_COLUMNP(c) ((c)->header.type == GRN_COLUMN_FIX_SIZE) -#define JA_COLUMNP(c) ((c)->header.type == GRN_COLUMN_VAR_SIZE) -#define IDX_COLUMNP(c) ((c)->header.type == GRN_COLUMN_INDEX) -#define COLUMNP(c) (RA_COLUMNP(c) || JA_COLUMNP(c) || IDX_COLUMNP(c)) -#define OPP(c) ((c)->header.type == GRN_CELL_OP) -#define STRVALUE(c) ((c)->u.b.value) -#define STRSIZE(c) ((c)->u.b.size) -#define NUMBERP(c) ((c)->header.type == GRN_CELL_INT || (c)->header.type == GRN_CELL_FLOAT) -#define SYMBOLP(c) ((c)->header.impl_flags & GRN_CELL_SYMBOL) -#define CONTINUATIONP(p) ((p)->header.type == GRN_CELL_CONTINUATION) -#define CLOSUREP(p) ((p)->header.type == GRN_CELL_CLOSURE || (p)->header.type == GRN_CELL_MACRO) -#define PROCP(p) ((p)->header.type == GRN_CELL_PROC) -#define PROCEDUREP(p) (PROCP(p) || CLOSUREP(p) || CONTINUATIONP(p) || NATIVE_FUNCP(p)) - -#define SETINT(c,v) ((c)->header.type = GRN_CELL_INT, (c)->u.i.i = (v)) -#define SETFLOAT(c,v) ((c)->header.type = GRN_CELL_FLOAT, (c)->u.d.d = (v)) -#define SETBULK(c,v,s) ((c)->header.type = GRN_CELL_STR, (c)->u.b.value = (v), (c)->u.b.size = (s)) -#define SETTIME(c,v) ((c)->header.type = GRN_CELL_TIME, memcpy(&(c)->u.tv, v, sizeof(grn_timeval))) - -#define CAR(c) ((c)->u.l.car) -#define CDR(c) ((c)->u.l.cdr) -#define CAAR(c) CAR(CAR(c)) -#define CADR(c) CAR(CDR(c)) -#define CDAR(c) CDR(CAR(c)) -#define CDDR(c) CDR(CDR(c)) -#define CADDR(c) CAR(CDDR(c)) -#define CADAR(p) CAR(CDAR(p)) -#define CADAAR(p) CAR(CDR(CAAR(p))) -#define CADDDR(p) CAR(CDR(CDDR(p))) -#define CDDDDR(p) CDR(CDR(CDDR(p))) - -#define IVALUE(p) ((p)->u.i.i) -#define FVALUE(p) ((p)->u.d.d) - -#define GRN_CELL_NEW(ctx,o) do {\ - if (!((o) = grn_cell_new(ctx))) { QLERR("obj_new failed"); }\ -} while(0) - -#define GRN_STR2OBJ(ctx,bulk,o) do {\ - (o) = grn_ql_mk_string(ctx, GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk));\ -} while(0) - -#define CONS(a,b) (grn_cell_cons(ctx, a, b)) - -#define INTERN(s) (grn_ql_mk_symbol(ctx, s, strlen(s))) - -#define POP(x,c) (PAIRP(c) ? ((x) = CAR(c), (c) = CDR(c), (x)) : (x = NIL)) - -#define SKIPSPACE(c) do {\ - unsigned int len;\ - while ((c)->cur < (c)->str_end && grn_isspace((c)->cur, (c)->encoding)) {\ - if (!(len = grn_charlen(ctx, (c)->cur, (c)->str_end))) { \ - (c)->cur = (c)->str_end;\ - break;\ - }\ - (c)->cur += len;\ - }\ -} while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* GRN_QL_H */ Deleted: lib/query.c (+0 -842) 100644 =================================================================== --- lib/query.c 2012-02-03 11:43:41 +0900 (cc28bb3) +++ /dev/null @@ -1,842 +0,0 @@ -/* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009 Brazil - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "groonga_in.h" -#include <string.h> -#include <ctype.h> -#include "snip.h" -#include "ql.h" -#include "hash.h" -#include "ii.h" - -/* query string parser and executor */ - -#define DEFAULT_WEIGHT 5 -#define DEFAULT_DECAYSTEP 2 -#define DEFAULT_MAX_INTERVAL 10 -#define DEFAULT_SIMILARITY_THRESHOLD 10 -#define DEFAULT_TERM_EXTRACT_POLICY 0 -#define DEFAULT_WEIGHT_VECTOR_SIZE 4096 - -struct _grn_query { - grn_obj_header header; - char *str; - char *cur; - char *str_end; - grn_operator default_op; - grn_select_optarg opt; - grn_operator default_mode; - int escalation_threshold; - int escalation_decaystep; - int weight_offset; - grn_hash *weight_set; - grn_encoding encoding; - grn_cell *expr; - int max_exprs; - int cur_expr; - int max_cells; - int cur_cell; - snip_cond *snip_conds; - grn_cell cell_pool[1]; /* dummy */ -}; - -inline static grn_cell * -cell_new(grn_query *q) -{ - if (q->cur_cell <= q->max_cells) { - grn_cell *c = &q->cell_pool[q->cur_cell++]; - return c; - } - return NULL; -} - -inline static void -cell_del(grn_query *q) -{ - if (q->cur_cell > 0) { q->cur_cell--; } -} - -inline static grn_cell * -cons(grn_query *q, grn_cell *car, grn_cell *cdr) -{ - grn_cell *c; - if ((c = cell_new(q))) { - c->header.type = GRN_CELL_LIST; - c->u.l.car = car; - c->u.l.cdr = cdr; - return c; - } else { - return NIL; - } -} - -inline static grn_cell * -token_new(grn_query *q, const char *start, const char *end) -{ - grn_cell *c; - if (start >= end) { return NIL; } - if ((c = cell_new(q))) { - unsigned int len = end - start; - c->header.type = GRN_CELL_STR; - c->u.b.value = (char *)start; - c->u.b.size = len; - q->cur_expr++; - return c; - } else { - return NIL; - } -} - -inline static grn_cell * -op_new(grn_query *q, int8_t op, int16_t weight, int8_t mode, int32_t option) -{ - grn_cell *c; - if ((c = cell_new(q))) { - c->header.type = GRN_CELL_OP; - c->u.op.op = op; - c->u.op.weight = weight; - c->u.op.mode = mode; - c->u.op.option = option; - return c; - } else { - return NIL; - } -} - -inline static void -skip_space(grn_ctx *ctx, grn_query *q) -{ - unsigned int len; - while (q->cur < q->str_end && grn_isspace(q->cur, q->encoding)) { - /* null check and length check */ - if (!(len = grn_charlen(ctx, q->cur, q->str_end))) { - q->cur = q->str_end; - break; - } - q->cur += len; - } -} - -inline static grn_cell * -get_phrase(grn_ctx *ctx, grn_query *q) -{ - char *start, *s, *d; - start = s = d = q->cur; - while (1) { - unsigned int len; - if (s >= q->str_end) { - q->cur = s; - break; - } - len = grn_charlen(ctx, s, q->str_end); - if (len == 0) { - /* invalid string containing malformed multibyte char */ - return NULL; - } else if (len == 1) { - if (*s == GRN_QUERY_QUOTER) { - q->cur = s + 1; - break; - } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) { - s++; - len = grn_charlen(ctx, s, q->str_end); - } - } - while (len--) { *d++ = *s++; } - } - return token_new(q, start, d); -} - -inline static grn_cell * -get_word(grn_ctx *ctx, grn_query *q, int *prefixp) -{ - char *start = q->cur, *end; - unsigned int len; - for (end = q->cur;; ) { - /* null check and length check */ - if (!(len = grn_charlen(ctx, end, q->str_end))) { - q->cur = q->str_end; - break; - } - if (grn_isspace(end, q->encoding) || - *end == GRN_QUERY_PARENR) { - q->cur = end; - break; - } - if (*end == GRN_QUERY_PREFIX) { - *prefixp = 1; - q->cur = end + 1; - break; - } - end += len; - } - return token_new(q, start, end); -} - -inline static grn_cell * -get_op(grn_query *q, grn_operator op, int weight) -{ - char *start, *end = q->cur; - int mode, option; - switch (*end) { - case 'S' : - mode = GRN_OP_SIMILAR; - start = ++end; - option = grn_atoi(start, q->str_end, (const char **)&end); - if (start == end) { option = DEFAULT_SIMILARITY_THRESHOLD; } - q->cur = end; - break; - case 'N' : - mode = GRN_OP_NEAR; - start = ++end; - option = grn_atoi(start, q->str_end, (const char **)&end); - if (start == end) { option = DEFAULT_MAX_INTERVAL; } - q->cur = end; - break; - case 'n' : - mode = GRN_OP_NEAR2; - start = ++end; - option = grn_atoi(start, q->str_end, (const char **)&end); - if (start == end) { option = DEFAULT_MAX_INTERVAL; } - q->cur = end; - break; - case 'T' : - mode = GRN_OP_TERM_EXTRACT; - start = ++end; - option = grn_atoi(start, q->str_end, (const char **)&end); - if (start == end) { option = DEFAULT_TERM_EXTRACT_POLICY; } - q->cur = end; - break; - case 'X' : /* force exact mode */ - op = GRN_OP_AND; - mode = GRN_OP_EXACT; - option = 0; - start = ++end; - q->cur = end; - break; - default : - return NIL; - } - return op_new(q, op, weight, mode, option); -} - -static grn_cell *get_expr(grn_ctx *ctx, grn_query *q); - -inline static grn_cell * -get_token(grn_ctx *ctx, grn_query *q) -{ - grn_cell *token = NIL; - grn_operator op = q->default_op; - { - int weight = DEFAULT_WEIGHT, prefixp = 0, mode = -1, option = 0; - skip_space(ctx, q); - if (q->cur_expr >= q->max_exprs || - q->cur_cell >= q->max_cells || - q->cur >= q->str_end) { return NIL; } - switch (*q->cur) { - case '\0' : - return NIL; - case GRN_QUERY_PARENR : - q->cur++; - return NIL; - case GRN_QUERY_QUOTEL : - q->cur++; - if ((token = get_phrase(ctx, q)) == NULL) { - return NIL; - } - break; - case GRN_QUERY_PREFIX : - q->cur++; - token = get_op(q, op, weight); - break; - case GRN_QUERY_AND : - q->cur++; - token = op_new(q, GRN_OP_AND, weight, mode, option); - break; - case GRN_QUERY_BUT : - q->cur++; - token = op_new(q, GRN_OP_BUT, weight, mode, option); - break; - case GRN_QUERY_ADJ_INC : - q->cur++; - if (weight < 127) { weight++; } - token = op_new(q, GRN_OP_ADJUST, weight, mode, option); - break; - case GRN_QUERY_ADJ_DEC : - q->cur++; - if (weight > -128) { weight--; } - token = op_new(q, GRN_OP_ADJUST, weight, mode, option); - break; - case GRN_QUERY_ADJ_NEG : - q->cur++; - token = op_new(q, GRN_OP_ADJUST, -1, mode, option); - break; - case GRN_QUERY_PARENL : - q->cur++; - token = get_expr(ctx, q); - break; - default : - if ((token = get_word(ctx, q, &prefixp)) && - token->u.b.value[0] == 'O' && - token->u.b.value[1] == 'R' && - token->u.b.size == 2) { - cell_del(q); - q->cur_expr--; - token = op_new(q, GRN_OP_OR, weight, mode, option); - } - break; - } - } - return cons(q, token, NIL); -} - -static grn_cell * -get_expr(grn_ctx *ctx, grn_query *q) -{ - grn_cell *r, *c, *c_; - for (c = r = get_token(ctx, q); c != NIL; c = c_) { - c_ = c->u.l.cdr = get_token(ctx, q); - } - return r; -} - -static const char * -get_weight_vector(grn_ctx *ctx, grn_query *query, const char *source) -{ - const char *p; - - if (!query->opt.weight_vector && - !query->weight_set && - !(query->opt.weight_vector = GRN_CALLOC(sizeof(int) * DEFAULT_WEIGHT_VECTOR_SIZE))) { - GRN_LOG(ctx, GRN_LOG_ALERT, "get_weight_vector malloc fail"); - return source; - } - for (p = source; p < query->str_end; ) { - unsigned int key; - int value; - - /* key, key is not zero */ - key = grn_atoui(p, query->str_end, &p); - if (!key || key > GRN_ID_MAX) { break; } - - /* value */ - if (*p == ':') { - p++; - value = grn_atoi(p, query->str_end, &p); - } else { - value = 1; - } - - if (query->weight_set) { - int *pval; - if (grn_hash_add(ctx, query->weight_set, &key, sizeof(unsigned int), (void **)&pval, NULL)) { - *pval = value; - } - } else if (key < DEFAULT_WEIGHT_VECTOR_SIZE) { - query->opt.weight_vector[key - 1] = value; - } else { - GRN_FREE(query->opt.weight_vector); - query->opt.weight_vector = NULL; - if (!(query->weight_set = grn_hash_create(ctx, NULL, sizeof(unsigned int), sizeof(int), - 0))) { - return source; - } - p = source; /* reparse */ - continue; - } - if (*p != ',') { break; } - p++; - } - return p; -} - -inline static void -get_pragma(grn_ctx *ctx, grn_query *q) -{ - char *start, *end = q->cur; - while (end < q->str_end && *end == GRN_QUERY_PREFIX) { - if (++end >= q->str_end) { break; } - switch (*end) { - case 'E' : - start = ++end; - q->escalation_threshold = grn_atoi(start, q->str_end, (const char **)&end); - while (end < q->str_end && (isdigit(*end) || *end == '-')) { end++; } - if (*end == ',') { - start = ++end; - q->escalation_decaystep = grn_atoi(start, q->str_end, (const char **)&end); - } - q->cur = end; - break; - case 'D' : - start = ++end; - while (end < q->str_end && *end != GRN_QUERY_PREFIX && !grn_isspace(end, q->encoding)) { - end++; - } - if (end > start) { - switch (*start) { - case 'O' : - q->default_op = GRN_OP_OR; - break; - case GRN_QUERY_AND : - q->default_op = GRN_OP_AND; - break; - case GRN_QUERY_BUT : - q->default_op = GRN_OP_BUT; - break; - case GRN_QUERY_ADJ_INC : - q->default_op = GRN_OP_ADJUST; - break; - } - } - q->cur = end; - break; - case 'W' : - start = ++end; - end = (char *)get_weight_vector(ctx, q, start); - q->cur = end; - break; - } - } -} - -static int -section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg) -{ - int *w; - grn_hash *s = (grn_hash *)arg; - if (s && grn_hash_get(ctx, s, &sid, sizeof(grn_id), (void **)&w)) { - return *w; - } else { - return 0; - } -} - -grn_query * -grn_query_open(grn_ctx *ctx, const char *str, unsigned int str_len, - grn_operator default_op, int max_exprs) -{ - grn_query *q; - int max_cells = max_exprs * 4; - if (!(q = GRN_MALLOC(sizeof(grn_query) + max_cells * sizeof(grn_cell) + str_len + 1))) { - GRN_LOG(ctx, GRN_LOG_ALERT, "grn_query_open malloc fail"); - return NULL; - } - q->header.type = GRN_QUERY; - q->str = (char *)&q->cell_pool[max_cells]; - memcpy(q->str, str, str_len); - q->str[str_len] = '\0'; - q->cur = q->str; - q->str_end = q->str + str_len; - q->default_op = default_op; - q->encoding = ctx->encoding; - q->max_exprs = max_exprs; - q->max_cells = max_cells; - q->cur_cell = 0; - q->cur_expr = 0; - q->escalation_threshold = GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD; - q->escalation_decaystep = DEFAULT_DECAYSTEP; - q->weight_offset = 0; - q->opt.weight_vector = NULL; - q->weight_set = NULL; - get_pragma(ctx, q); - q->expr = get_expr(ctx, q); - q->opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE; - q->opt.func = q->weight_set ? section_weight_cb : NULL; - q->opt.func_arg = q->weight_set; - q->snip_conds = NULL; - return q; -} - -unsigned int -grn_query_rest(grn_ctx *ctx, grn_query *q, const char ** const rest) -{ - if (!q) { return 0; } - if (rest) { - *rest = q->cur; - } - return (unsigned int)(q->str_end - q->cur); -} - -grn_rc -grn_query_close(grn_ctx *ctx, grn_query *q) -{ - if (!q) { return GRN_INVALID_ARGUMENT; } - if (q->opt.weight_vector) { - GRN_FREE(q->opt.weight_vector); - } - if (q->weight_set) { - grn_hash_close(ctx, q->weight_set); - } - if (q->snip_conds) { - snip_cond *sc; - for (sc = q->snip_conds; sc < q->snip_conds + q->cur_expr; sc++) { - grn_snip_cond_close(ctx, sc); - } - GRN_FREE(q->snip_conds); - } - GRN_FREE(q); - return GRN_SUCCESS; -} - -/* FIXME: for test */ -grn_rc -grn_query_str(grn_query *q, const char **str, unsigned int *len) -{ - if (str) { *str = q->str; } - if (len) { *len = q->str_end - q->str; } - return GRN_SUCCESS; -} - -static void -scan_keyword(snip_cond *sc, grn_str *str, grn_id section, - grn_operator op, grn_select_optarg *optarg, - int *found, int *score) -{ - int tf; - int w = 1; - for (tf = 0; ; tf++) { - grn_bm_tunedbm(sc, str, 0); - if (sc->stopflag == SNIPCOND_STOP) { break; } - } - if (optarg->vector_size) { - if (!optarg->weight_vector) { - w = optarg->vector_size; - } else if (section) { - w = (section <= optarg->vector_size ? - optarg->weight_vector[section - 1] : 0); - } - } - switch (op) { - case GRN_OP_OR : - if (tf) { - *found = 1; - *score += w * tf; - } - break; - case GRN_OP_AND : - if (tf) { - *score += w * tf; - } else { - *found = 0; - } - break; - case GRN_OP_BUT : - if (tf) { - *found = 0; - } - break; - case GRN_OP_ADJUST : - *score += w * tf; - default : - break; - } -} - -/* TODO: delete overlapping logic with exec_query */ -static grn_rc -scan_query(grn_ctx *ctx, grn_query *q, grn_str *nstr, grn_id section, grn_cell *c, snip_cond **sc, - grn_operator op, int flags, int *found, int *score) -{ - int _found = 0, _score = 0; - grn_cell *e, *ope = NIL; - grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op; - while (c != NIL) { - POP(e, c); - switch (e->header.type) { - case GRN_CELL_OP : - if (opp == &op0 && e->u.op.op == GRN_OP_BUT) { - POP(e, c); - } else { - ope = e; - op1 = ope->u.op.op; - } - continue; - case GRN_CELL_STR : - if (ope != NIL) { - q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode; - q->opt.max_interval = q->opt.similarity_threshold = ope->u.op.option; - if (!q->opt.weight_vector) { - q->opt.vector_size = ope->u.op.weight + q->weight_offset; - } - } else { - q->opt.mode = q->default_mode; - q->opt.max_interval = DEFAULT_MAX_INTERVAL; - q->opt.similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD; - if (!q->opt.weight_vector) { - q->opt.vector_size = DEFAULT_WEIGHT + q->weight_offset; - } - } - if ((flags & GRN_QUERY_SCAN_ALLOCCONDS)) { - grn_rc rc; - /* NOTE: GRN_SNIP_NORMALIZE = GRN_QUERY_SCAN_NORMALIZE */ - if ((rc = grn_snip_cond_init(ctx, *sc, e->u.b.value, e->u.b.size, - q->encoding, flags & GRN_SNIP_NORMALIZE))) { - return rc; - } - } else { - grn_snip_cond_reinit(*sc); - } - scan_keyword(*sc, nstr, section, *opp, &q->opt, &_found, &_score); - (*sc)++; - break; - case GRN_CELL_LIST : - scan_query(ctx, q, nstr, section, e, sc, *opp, flags, &_found, &_score); - break; - default : - GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query! (%d)", e->header.type); - break; - } - opp = &op1; - ope = NIL; - op1 = q->default_op; - } - switch (op) { - case GRN_OP_OR : - *found |= _found; - *score += _score; - break; - case GRN_OP_AND : - *found &= _found; - *score += _score; - break; - case GRN_OP_BUT : - *found &= !_found; - break; - case GRN_OP_ADJUST : - *score += _score; - break; - default : - break; - } - return GRN_SUCCESS; -} - -static grn_rc -alloc_snip_conds(grn_ctx *ctx, grn_query *q) -{ - if (!(q->snip_conds = GRN_CALLOC(sizeof(snip_cond) * q->cur_expr))) { - GRN_LOG(ctx, GRN_LOG_ALERT, "snip_cond allocation failed"); - return GRN_NO_MEMORY_AVAILABLE; - } - return GRN_SUCCESS; -} - -grn_rc -grn_query_scan(grn_ctx *ctx, grn_query *q, const char **strs, unsigned int *str_lens, unsigned int nstrs, - int flags, int *found, int *score) -{ - unsigned int i; - grn_rc rc; - if (!q || !strs || !nstrs) { return GRN_INVALID_ARGUMENT; } - *found = *score = 0; - if (!q->snip_conds) { - if ((rc = alloc_snip_conds(ctx, q))) { return rc; } - flags |= GRN_QUERY_SCAN_ALLOCCONDS; - } else if (flags & GRN_QUERY_SCAN_ALLOCCONDS) { - GRN_LOG(ctx, GRN_LOG_WARNING, "invalid flags specified on grn_query_scan"); - return GRN_INVALID_ARGUMENT; - } - for (i = 0; i < nstrs; i++) { - grn_str *n; - snip_cond *sc = q->snip_conds; - int f = GRN_STR_WITH_CHECKS | GRN_STR_REMOVEBLANK; - if (flags & GRN_QUERY_SCAN_NORMALIZE) { f |= GRN_STR_NORMALIZE; } - n = grn_str_open(ctx, *(strs + i), *(str_lens + i), f); - if (!n) { return GRN_NO_MEMORY_AVAILABLE; } - if ((rc = scan_query(ctx, q, n, i + 1, q->expr, &sc, GRN_OP_OR, flags, found, score))) { - grn_str_close(ctx, n); - return rc; - } - flags &= ~GRN_QUERY_SCAN_ALLOCCONDS; - grn_str_close(ctx, n); - } - return GRN_SUCCESS; -} - -/* TODO: delete overlapping logic with exec_query */ -static grn_rc -snip_query(grn_ctx *ctx, grn_query *q, grn_snip *snip, grn_cell *c, grn_operator op, - unsigned int n_tags, int c_but, - const char **opentags, unsigned int *opentag_lens, - const char **closetags, unsigned int *closetag_lens) -{ - grn_cell *e, *ope = NIL; - grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op; - while (c != NIL) { - POP(e, c); - switch (e->header.type) { - case GRN_CELL_OP : - ope = e; - op1 = ope->u.op.op; - continue; - case GRN_CELL_STR : - if (ope != NIL) { - q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode; - } else { - q->opt.mode = q->default_mode; - } - if (!(c_but ^ (*opp == GRN_OP_BUT))) { - grn_rc rc; - unsigned int i = snip->cond_len % n_tags; - if ((rc = grn_snip_add_cond(ctx, snip, e->u.b.value, e->u.b.size, - opentags[i], opentag_lens[i], - closetags[i], closetag_lens[i]))) { - return rc; - } - } - break; - case GRN_CELL_LIST : - snip_query(ctx, q, snip, e, *opp, n_tags, (*opp == GRN_OP_BUT) ? c_but ^ 1 : c_but, - opentags, opentag_lens, closetags, closetag_lens); - break; - default : - GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query!! (%d)", e->header.type); - break; - } - opp = &op1; - ope = NIL; - op1 = q->default_op; - } - return GRN_SUCCESS; -} - -grn_snip * -grn_query_snip(grn_ctx *ctx, grn_query *query, int flags, - unsigned int width, unsigned int max_results, - unsigned int n_tags, - const char **opentags, unsigned int *opentag_lens, - const char **closetags, unsigned int *closetag_lens, - grn_snip_mapping *mapping) -{ - grn_snip *res; - if (!(res = grn_snip_open(ctx, flags, width, max_results, - NULL, 0, NULL, 0, mapping))) { - return NULL; - } - if (snip_query(ctx, query, res, query->expr, GRN_OP_OR, n_tags, 0, - opentags, opentag_lens, closetags, closetag_lens)) { - grn_snip_close(ctx, res); - return NULL; - } - return res; -} - -static void -exec_search(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_cell *c, - grn_hash *r, grn_operator op) -{ - grn_hash *s; - grn_cell *e, *ope = NIL; - int n = *r->n_entries; - grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op; - if (!n && op != GRN_OP_OR) { return; } - if (n) { - s = grn_hash_create(ctx, NULL, r->key_size, r->value_size, r->obj.header.flags); - s->obj.header.impl_flags = 0; - s->obj.header.domain = r->obj.header.domain; - s->obj.range = r->obj.range; - s->obj.max_n_subrecs = r->obj.max_n_subrecs; - s->obj.subrec_size = r->obj.subrec_size; - s->obj.subrec_offset = r->obj.subrec_offset; - s->obj.id = r->obj.id; - s->obj.db = r->obj.db; - s->obj.source = r->obj.source; - s->obj.source_size = r->obj.source_size; - /* - grn_hook_entry entry; - for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { - s->obj.hooks[entry] = NULL; - } - */ - } else { - s = r; - } - while (c != NIL) { - POP(e, c); - switch (e->header.type) { - case GRN_CELL_OP : - if (opp == &op0 && e->u.op.op == GRN_OP_BUT) { - POP(e, c); - } else { - ope = e; - op1 = ope->u.op.op; - } - continue; - case GRN_CELL_STR : - if (ope != NIL) { - q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode; - q->opt.max_interval = q->opt.similarity_threshold = ope->u.op.option; - if (!q->opt.weight_vector) { - q->opt.vector_size = ope->u.op.weight + q->weight_offset; - } - if (ope->u.op.mode == GRN_OP_SIMILAR) { - q->opt.max_interval = q->default_mode; - } - } else { - q->opt.mode = q->default_mode; - q->opt.max_interval = DEFAULT_MAX_INTERVAL; - q->opt.similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD; - if (!q->opt.weight_vector) { - q->opt.vector_size = DEFAULT_WEIGHT + q->weight_offset; - } - } - if (grn_ii_select(ctx, i, e->u.b.value, e->u.b.size, s, *opp, &q->opt)) { - GRN_LOG(ctx, GRN_LOG_ERROR, "grn_inv_select on exec_search failed !"); - return; - } - break; - case GRN_CELL_LIST : - exec_search(ctx, i, q, e, s, *opp); - break; - default : - GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query (%d)", e->header.type); - break; - } - opp = &op1; - ope = NIL; - op1 = q->default_op; - } - if (n) { - grn_table_setoperation(ctx, (grn_obj *)r, (grn_obj *)s, (grn_obj *)r, op); - grn_hash_close(ctx, s); - } -} - -grn_rc -grn_query_search(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_hash *r, grn_operator op) -{ - int p = q->escalation_threshold; - // dump_query(q, q->expr, 0); - // grn_log("escalation_threshold=%d", p); - if (p >= 0 || (-p & 1)) { - q->default_mode = GRN_OP_EXACT; - exec_search(ctx, i, q, q->expr, r, op); - GRN_LOG(ctx, GRN_LOG_INFO, "hits(exact)=%d", *r->n_entries); - } - if ((p >= 0) ? (p >= *r->n_entries) : (-p & 2)) { - q->weight_offset -= q->escalation_decaystep; - q->default_mode = GRN_OP_UNSPLIT; - exec_search(ctx, i, q, q->expr, r, op); - GRN_LOG(ctx, GRN_LOG_INFO, "hits(unsplit)=%d", *r->n_entries); - } - if ((p >= 0) ? (p >= *r->n_entries) : (-p & 4)) { - q->weight_offset -= q->escalation_decaystep; - q->default_mode = GRN_OP_PARTIAL; - exec_search(ctx, i, q, q->expr, r, op); - GRN_LOG(ctx, GRN_LOG_INFO, "hits(partial)=%d", *r->n_entries); - } - return GRN_SUCCESS; -} Deleted: lib/scm.c (+0 -3494) 100644 =================================================================== --- lib/scm.c 2012-02-03 11:43:41 +0900 (47233f0) +++ /dev/null @@ -1,3494 +0,0 @@ -/* -*- c-basic-offset: 2 -*- */ -/* - Copyright(C) 2009-2012 Brazil - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* Groonga Query Language is based on Mini-Scheme, original credits follow */ - -/* - * ---------- Mini-Scheme Interpreter Version 0.85 ---------- - * - * coded by Atsushi Moriwaki (11/5/1989) - * - * E-MAIL : moriw****@kurim***** - * - * THIS SOFTWARE IS IN THE PUBLIC DOMAIN - * ------------------------------------ - * This software is completely free to copy, modify and/or re-distribute. - * But I would appreciate it if you left my name on the code as the author. - * - */ -/*-- - * - * This version has been modified by R.C. Secrist. - * - * Mini-Scheme is now maintained by Akira KIDA. - * - * This is a revised and modified version by Akira KIDA. - * current version is 0.85k4 (15 May 1994) - * - * Please send suggestions, bug reports and/or requests to: - * <SDI00****@nifty*****> - *-- - */ - -#include "groonga_in.h" -#include <fcntl.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include "ql.h" - -#ifdef stat -# undef stat -#endif /* stat */ - -#define InitFile "init.scm" - -/* global variables */ - -grn_cell *grn_ql_nil; /* special cell representing empty cell */ -grn_cell *grn_ql_t; /* special cell representing #t */ -grn_cell *grn_ql_f; /* special cell representing #f */ - -/* sen query language */ - -/* todo : update set-car! set-cdr! - -inline static void -obj_ref(grn_cell *o) -{ - if (o->nrefs < 0xffff) { o->nrefs++; } - if (PAIRP(o)) { // todo : check cycle - if (CAR(o) != NIL) { obj_ref(CAR(o)); } - if (CDR(o) != NIL) { obj_ref(CDR(o)); } - } -} - -inline static void -obj_unref(grn_cell *o) -{ - if (!o->nrefs) { - GRN_LOG(ctx, GRN_LOG_ERROR, "o->nrefs corrupt"); - return; - } - if (o->nrefs < 0xffff) { o->nrefs--; } - if (PAIRP(o)) { // todo : check cycle - if (CAR(o) != NIL) { obj_unref(CAR(o)); } - if (CDR(o) != NIL) { obj_unref(CDR(o)); } - } -} - -inline static void -rplaca(grn_ctx *ctx, grn_cell *a, grn_cell *b) -{ - if (a->nrefs) { - ctx->impl->nbinds++; - if (a->u.l.car) { - ctx->impl->nunbinds++; - obj_unref(a->u.l.car); - } - if (b) { obj_ref(b); } - } - a->u.l.car = b; -} - -inline static void -rplacd(grn_ctx *ctx, grn_cell *a, grn_cell *b) -{ - if (a->nrefs) { - ctx->impl->nbinds++; - if (a->u.l.cdr) { - ctx->impl->nunbinds++; - obj_unref(a->u.l.cdr); - } - if (b) { obj_ref(b); } - } - a->u.l.cdr = b; -} - -*/ - -grn_rc -grn_obj2int(grn_ctx *ctx, grn_cell *o) -{ - grn_rc rc = GRN_INVALID_ARGUMENT; - if (o) { - switch (o->header.type) { - case GRN_CELL_STR : - if (o->u.b.size) { - const char *end = o->u.b.value + o->u.b.size, *rest; - int64_t i = grn_atoll(o->u.b.value, end, &rest); - if (rest == end) { - grn_cell_clear(ctx, o); - SETINT(o, i); - rc = GRN_SUCCESS; - } - } - break; - case GRN_CELL_INT : - rc = GRN_SUCCESS; - break; - default : - break; - } - } - return rc; -} - -static void -symbol2str(void *x, char *buf) -{ - uint16_t symname_size; - const char *symname = _grn_hash_strkey_by_val(x, &symname_size); - memcpy(buf, symname, symname_size); - buf[symname_size] = '\0'; -} - -static int -keywordp(void *x) -{ - uint16_t symname_size; - const char *symname = _grn_hash_strkey_by_val(x, &symname_size); - return symname_size && *symname == ':'; -} - -/* get new symbol */ -grn_cell * -grn_ql_mk_symbol(grn_ctx *ctx, const char *name, int name_size) -{ - grn_cell *x; - if (!grn_hash_add(ctx, ctx->impl->symbols, name, name_size, (void **) &x, NULL)) { - return F; - } - if (!x->header.impl_flags) { - x->header.impl_flags |= GRN_CELL_SYMBOL; - x->header.type = GRN_VOID; - } - if (x->header.type == GRN_VOID && ctx->impl->db) { - uint16_t symname_size; - const char *symname = _grn_hash_strkey_by_val(x, &symname_size); - grn_obj *obj = grn_ctx_get(ctx, symname, symname_size); - if (obj) { grn_ql_obj_bind(obj, x); } - } - return x; -} - -grn_cell * -grn_ql_at(grn_ctx *ctx, const char *key) -{ - grn_cell *o; - if (!grn_hash_get(ctx, ctx->impl->symbols, key, strlen(key), (void **) &o)) { - return NULL; - } - return o; -} - -grn_cell * -grn_ql_def_native_func(grn_ctx *ctx, const char *name, grn_ql_native_func *func) -{ - grn_cell *o = INTERN(name); - if (o != F) { - o->header.type = GRN_VOID; - o->header.impl_flags |= GRN_CELL_NATIVE; - o->u.o.func = func; - } - return o; -} - -/* -inline static void -grn_ctx_igc(grn_ctx *ctx) -{ - uint32_t i; - grn_cell *o; - grn_set_eh *ep; - for (i = ctx->impl->lseqno; i != ctx->impl->seqno; i++) { - if ((ep = grn_set_at(ctx->impl->objects, &i, (void **) &o))) { - if (ctx->impl->nbinds && - (o->nrefs || - (BULKP(o) && (o->header.impl_flags & GRN_OBJ_ALLOCATED)))) { continue; } - grn_cell_clear(ctx, o); - grn_set_del(ctx->impl->objects, ep); - } - } - ctx->impl->lseqno = ctx->impl->seqno; - ctx->impl->nbinds = 0; -} -*/ - -#define MARKP(p) ((p)->header.impl_flags & GRN_CELL_MARKED) -#define REFERERP(p) ((p)->header.type & GRN_CELL_LIST) -#define SETREFERER(p) ((p)->header.type |= GRN_CELL_LIST) -#define UNSETREFERER(p) ((p)->header.type &= ~GRN_CELL_LIST) - -/*-- - * We use algorithm E (Knuth, The Art of Computer Programming Vol.1, - * sec.3.5) for marking. - */ -inline static void -obj_mark(grn_ctx *ctx, grn_cell *o) -{ - grn_cell *t, *q, *p; - t = NULL; - p = o; - // if (MARKP(o)) { return; } -E2: - p->header.impl_flags |= GRN_CELL_MARKED; - // if (!o->nrefs) { GRN_LOG(ctx, GRN_LOG_ERROR, "obj->nrefs corrupt"); } - if (BULKP(o) && !(o->header.impl_flags & GRN_OBJ_ALLOCATED)) { - char *b = GRN_MALLOC(o->u.b.size + 1); - if (b) { - memcpy(b, o->u.b.value, o->u.b.size); - b[o->u.b.size] = '\0'; - o->u.b.value = b; - o->header.impl_flags |= GRN_OBJ_ALLOCATED; - } - } - if (!REFERERP(p)) { goto E6; } - q = CAR(p); - if (q && !MARKP(q)) { - UNSETREFERER(p); - CAR(p) = t; - t = p; - p = q; - goto E2; - } -E5: - q = CDR(p); - if (q && !MARKP(q)) { - CDR(p) = t; - t = p; - p = q; - goto E2; - } -E6: - if (!t) { return; } - q = t; - if (!REFERERP(q)) { - SETREFERER(q); - t = CAR(q); - CAR(q) = p; - p = q; - goto E5; - } else { - t = CDR(q); - CDR(q) = p; - p = q; - goto E6; - } -} - -#define MARK2P(p) ((p)->header.impl_flags & GRN_CELL_MARK2) - -grn_rc -grn_ql_obj_mark(grn_ctx *ctx, grn_cell *o) -{ - grn_cell *t, *q, *p; - t = NULL; - p = o; - if (MARK2P(o)) { return GRN_INVALID_ARGUMENT; } -E2: - p->header.impl_flags |= GRN_CELL_MARK2; - if (!REFERERP(p)) { goto E6; } - q = CAR(p); - if (q && !MARK2P(q)) { - UNSETREFERER(p); - CAR(p) = t; - t = p; - p = q; - goto E2; - } -E5: - q = CDR(p); - if (q && !MARK2P(q)) { - CDR(p) = t; - t = p; - p = q; - goto E2; - } -E6: - if (!t) { return GRN_SUCCESS; } - q = t; - if (!REFERERP(q)) { - SETREFERER(q); - t = CAR(q); - CAR(q) = p; - p = q; - goto E5; - } else { - t = CDR(q); - CDR(q) = p; - p = q; - goto E6; - } - return GRN_SUCCESS; -} - -grn_rc -grn_ql_obj_unmark(grn_ctx *ctx, grn_cell *o) -{ - grn_cell *t, *q, *p; - t = NULL; - p = o; - if (!MARK2P(o)) { return GRN_INVALID_ARGUMENT; } -E2: - p->header.impl_flags &= ~GRN_CELL_MARK2; - if (!REFERERP(p)) { goto E6; } - q = CAR(p); - if (q && MARK2P(q)) { - UNSETREFERER(p); - CAR(p) = t; - t = p; - p = q; - goto E2; - } -E5: - q = CDR(p); - if (q && MARK2P(q)) { - CDR(p) = t; - t = p; - p = q; - goto E2; - } -E6: - if (!t) { return GRN_SUCCESS; } - q = t; - if (!REFERERP(q)) { - SETREFERER(q); - t = CAR(q); - CAR(q) = p; - p = q; - goto E5; - } else { - t = CDR(q); - CDR(q) = p; - p = q; - goto E6; - } - return GRN_SUCCESS; -} - -grn_rc -grn_ctx_mgc(grn_ctx *ctx) -{ - /* - if (!(sc = grn_set_cursor_open(ctx->impl->symbols))) { return GRN_NO_MEMORY_AVAILABLE; } - { - grn_cell *o; - while (grn_set_cursor_next(sc, NULL, (void **) &o)) { obj_mark(o); } - grn_set_cursor_close(sc); - } - */ - obj_mark(ctx, ctx->impl->global_env); - - /* mark current registers */ - obj_mark(ctx, ctx->impl->args); - obj_mark(ctx, ctx->impl->envir); - obj_mark(ctx, ctx->impl->code); - obj_mark(ctx, ctx->impl->dump); - obj_mark(ctx, ctx->impl->value); - obj_mark(ctx, ctx->impl->phs); - - ctx->impl->n_entries = 0; - { - grn_cell *o; - GRN_ARRAY_EACH(ctx, ctx->impl->objects, 0, 0, id, &o, { - if (o->header.impl_flags & (GRN_CELL_MARKED|GRN_CELL_MARK2)) { - o->header.impl_flags &= ~GRN_CELL_MARKED; - ctx->impl->n_entries++; - } else { - grn_cell_clear(ctx, o); - grn_array_delete_by_id(ctx, ctx->impl->objects, id, NULL); - } - }); - } - { - grn_tmp_db_obj *o; - GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { - if (o->cell.header.impl_flags & (GRN_CELL_MARKED|GRN_CELL_MARK2)) { - o->cell.header.impl_flags &= ~GRN_CELL_MARKED; - ctx->impl->n_entries++; - } else { - if (((grn_obj *)o->obj)->header.type != GRN_EXPR && - ((grn_obj *)o->obj)->header.type != GRN_PROC && - ((grn_obj *)o->obj)->header.domain == GRN_ID_NIL) { - grn_obj_close(ctx, (grn_obj *)o->obj); - } - } - }); - } - ctx->impl->lseqno = ctx->impl->seqno; - ctx->impl->nbinds = 0; - ctx->impl->nunbinds = 0; - return GRN_SUCCESS; -} - -inline static void Eval_Cycle(grn_ctx *ctx); - -/* ========== Evaluation Cycle ========== */ - -/* operator code */ - -enum { - OP_T0LVL = GRN_OP_T0LVL, - OP_ERR0 = GRN_OP_ERR0, - OP_LOAD, - OP_T1LVL, - OP_READ, - OP_VALUEPRINT, - OP_EVAL, - OP_E0ARGS, - OP_E1ARGS, - OP_APPLY, - OP_DOMACRO, - OP_LAMBDA, - OP_QUOTE, - OP_DEF0, - OP_DEF1, - OP_BEGIN, - OP_IF0, - OP_IF1, - OP_SET0, - OP_SET1, - OP_LET0, - OP_LET1, - OP_LET2, - OP_LET0AST, - OP_LET1AST, - OP_LET2AST, - OP_LET0REC, - OP_LET1REC, - OP_LET2REC, - OP_COND0, - OP_COND1, - OP_DELAY, - OP_AND0, - OP_AND1, - OP_OR0, - OP_OR1, - OP_C0STREAM, - OP_C1STREAM, - OP_0MACRO, - OP_1MACRO, - OP_CASE0, - OP_CASE1, - OP_CASE2, - OP_PEVAL, - OP_PAPPLY, - OP_CONTINUATION, - OP_SETCAR, - OP_SETCDR, - OP_FORCE, - OP_ERR1, - OP_PUT, - OP_GET, - OP_QUIT, - OP_SDOWN, - OP_RDSEXPR, - OP_RDLIST, - OP_RDDOT, - OP_RDQUOTE, - OP_RDQQUOTE, - OP_RDUNQUOTE, - OP_RDUQTSP, - OP_NATIVE, - OP_QQUOTE0, - OP_QQUOTE1, - OP_QQUOTE2 -}; - -grn_cell * -grn_ql_feed(grn_ctx *ctx, char *str, uint32_t str_size, int mode) -{ - if (GRN_QL_WAITINGP(ctx)) { - GRN_BULK_REWIND(ctx->impl->outbuf); - GRN_BULK_REWIND(&ctx->impl->subbuf); - ctx->impl->bufcur = 0; - } - for (;;) { - switch (ctx->stat) { - case GRN_QL_TOPLEVEL : - ctx->impl->co.mode &= ~GRN_CTX_HEAD; - Eval_Cycle(ctx); - break; - case GRN_QL_WAIT_EXPR : - ctx->impl->co.mode = mode; - ctx->impl->cur = str; - ctx->impl->str_end = str + str_size; - Eval_Cycle(ctx); - break; - case GRN_QL_WAIT_ARG : - ctx->impl->co.mode = mode; - if ((mode & GRN_CTX_HEAD)) { - ctx->impl->cur = str; - ctx->impl->str_end = str + str_size; - } else { - char *buf; - grn_cell *ph = CAR(ctx->impl->phs); - if (!(buf = GRN_MALLOC(str_size + 1))) { - return NIL; - } - memcpy(buf, str, str_size); - buf[str_size] = '\0'; - ph->header.impl_flags |= GRN_OBJ_ALLOCATED; - ph->u.b.value = buf; - ph->u.b.size = str_size; - ctx->impl->phs = CDR(ctx->impl->phs); - } - if ((ctx->impl->phs == NIL) || (mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) { - ctx->stat = GRN_QL_EVAL; - } - break; - case GRN_QL_EVAL : - Eval_Cycle(ctx); - break; - case GRN_QL_WAIT_DATA : - ctx->impl->co.mode = mode; - if ((mode & GRN_CTX_HEAD)) { - ctx->impl->args = NIL; - ctx->impl->cur = str; - ctx->impl->str_end = str + str_size; - } else { - ctx->impl->arg.u.b.value = str; - ctx->impl->arg.u.b.size = str_size; - ctx->impl->arg.header.type = GRN_CELL_STR; - ctx->impl->arg.header.impl_flags = GRN_OBJ_ALLOCATED; - ctx->impl->args = &ctx->impl->arg; - } - /* fall through */ - case GRN_QL_NATIVE : - GRN_ASSERT(ctx->impl->co.func); - ctx->impl->value = ctx->impl->co.func(ctx, ctx->impl->args, &ctx->impl->co); - if (ERRP(ctx, GRN_ERROR)) { ctx->stat = GRN_CTX_QUITTING; return F; } - ERRCLR(ctx); - if (ctx->impl->co.last && !(ctx->impl->co.mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) { - ctx->stat = GRN_QL_WAIT_DATA; - } else { - ctx->impl->co.mode = 0; - Eval_Cycle(ctx); - } - break; - case GRN_CTX_QUITTING : - case GRN_CTX_QUIT : - return NIL; - } - if (ERRP(ctx, GRN_ERROR)) { ctx->stat = GRN_CTX_QUITTING; return F; } - if (GRN_QL_WAITINGP(ctx)) { /* waiting input data */ - if (ctx->impl->inbuf) { - GRN_FREE(ctx->impl->inbuf); - ctx->impl->inbuf = NULL; - } - break; - } - if ((ctx->stat & 0x40) && GRN_QL_GET_MODE(ctx) == grn_ql_step) { - break; - } - } - return NIL; -} - -/**** sexp parser ****/ - -inline static void -skipline(grn_ctx *ctx) -{ - while (ctx->impl->cur < ctx->impl->str_end) { - if (*ctx->impl->cur++ == '\n') { break; } - } -} - -/*************** scheme interpreter ***************/ - -# define BACKQUOTE '`' - -#include <stdio.h> -#include <ctype.h> - -/* macros for cell operations */ -#define HASPROP(p) ((p)->header.impl_flags & GRN_CELL_SYMBOL) -#define SYMPROP(p) CDR(p) -#define SYNTAXP(p) ((p)->header.type == GRN_CELL_SYNTAX) -#define SYNTAXNUM(p) ((p)->header.domain) -#define PROCNUM(p) IVALUE(p) -#define MACROP(p) ((p)->header.type == GRN_CELL_MACRO) -#define CLOSURE_CODE(p) CAR(p) -#define CLOSURE_ENV(p) CDR(p) -#define CONT_DUMP(p) CDR(p) -#define PROMISEP(p) ((p)->header.impl_flags & GRN_CELL_PROMISE) -#define SETPROMISE(p) (p)->header.impl_flags |= GRN_CELL_PROMISE -#define LAMBDA (INTERN("lambda")) -#define QUOTE (INTERN("quote")) -#define QQUOTE (INTERN("quasiquote")) -#define UNQUOTE (INTERN("unquote")) -#define UNQUOTESP (INTERN("unquote-splicing")) - -/* get new cell. parameter a, b is marked by gc. */ -#define GET_CELL(ctx,a,b,o) GRN_CELL_NEW(ctx, o) - -/* get number atom */ -inline static grn_cell * -mk_number(grn_ctx *ctx, int64_t num) -{ - grn_cell *x; - GRN_CELL_NEW(ctx, x); - SETINT(x, num); - return x; -} - -/* get new string */ -grn_cell * -grn_ql_mk_string(grn_ctx *ctx, const char *str, unsigned int len) -{ - grn_cell *x = grn_cell_alloc(ctx, len); - if (!x) { return F; } - memcpy(x->u.b.value, str, len); - x->u.b.value[len] = '\0'; - return x; -} - -inline static grn_cell * -mk_const_string(grn_ctx *ctx, const char *str) -{ - grn_cell *x; - GRN_CELL_NEW(ctx, x); - x->header.impl_flags = 0; - x->header.type = GRN_CELL_STR; - x->u.b.value = (char *)str; - x->u.b.size = strlen(str); - return x; -} - -grn_cell * -grn_ql_mk_symbol2(grn_ctx *ctx, const char *q, unsigned int len, int kwdp) -{ - char buf[GRN_TABLE_MAX_KEY_SIZE], *p = buf; - if (len + 1 >= GRN_TABLE_MAX_KEY_SIZE) { QLERR("too long symbol"); } - if (kwdp) { - *p++ = ':'; - memcpy(p, q, len); - len++; - } else { - memcpy(p, q, len); - } - return grn_ql_mk_symbol(ctx, buf, len); -} - -static grn_cell * -str2num(grn_ctx *ctx, const char *str, unsigned int len) -{ - const char *cur, *str_end = str + len; - int64_t i = grn_atoll(str, str_end, &cur); - if (cur == str_end) { return mk_number(ctx, i); } - if (cur != str) { /* todo : support #i notation */ - char *end, buf0[128], *buf = len < 128 ? buf0 : GRN_MALLOC(len + 1); - if (buf) { - double d; - memcpy(buf, str, len); - buf[len] = '\0'; - errno = 0; - d = strtod(buf, &end); - if (!(len < 128)) { GRN_FREE(buf); } - if (!errno && buf + len == end) { - grn_cell *x; - GRN_CELL_NEW(ctx, x); - SETFLOAT(x, d); - return x; - } - } - } - return NIL; -} - -/* make symbol or number atom from string */ -static grn_cell * -mk_atom(grn_ctx *ctx, char *str, unsigned int len, grn_cell *v) -{ - grn_cell **vp = &v, *p; - const char *cur, *last, *str_end = str + len; - if ((p = str2num(ctx, str, len)) != NIL) { return p; } - for (last = cur = str; cur < str_end; cur += len) { - if (!(len = grn_charlen(ctx, cur, str_end))) { break; } - if (*cur == '.') { - if (last < cur) { *vp = grn_ql_mk_symbol2(ctx, last, cur - last, str != last); } - v = CONS(v, CONS(NIL, NIL)); - vp = &CADR(v); - last = cur + 1; - } - } - if (last < cur) { *vp = grn_ql_mk_symbol2(ctx, last, cur - last, str != last); } - return v; -} - -/* make constant */ -inline static grn_cell * -mk_const(grn_ctx *ctx, char *name, unsigned int len) -{ - char tmp[256]; - char tmp2[256]; - /* todo : rewirte with grn_str_* functions */ - if (len == 1) { - if (*name == 't') { - return T; - } else if (*name == 'f') { - return F; - } - } else if (len > 1) { - if (*name == 'p' && name[1] == '<' && name[12] == '>') {/* #p (GRN_CELL_OBJECT) */ - grn_id cls = grn_btoi(name + 2); - if (cls) { - grn_id self = grn_btoi(name + 7); - if (self) { - grn_cell * v = grn_ql_obj_new(ctx, cls, self); - if (len > 13 && name[13] == '.') { - return mk_atom(ctx, name + 13, len - 13, v); - } else { - return v; - } - } - } - } else if (*name == ':' && name[1] == '<') {/* #: (GRN_CELL_TIME) */ - grn_cell *x; - grn_timeval tv; - const char *cur; - tv.tv_sec = grn_atoi(name + 2, name + len, &cur); - if (cur >= name + len || *cur != '.') { - QLERR("illegal time format '%s'", name); - } - tv.tv_nsec = grn_atoi(cur + 1, name + len, &cur); - if (cur >= name + len || *cur != '>') { - QLERR("illegal time format '%s'", name); - } - GRN_CELL_NEW(ctx, x); - SETTIME(x, &tv); - return x; - } else if (*name == 'o') {/* #o (octal) */ - long long unsigned int x; - len = (len > 255) ? 255 : len - 1; - memcpy(tmp2, name + 1, len); - tmp2[len] = '\0'; - sprintf(tmp, "0%s", tmp2); - sscanf(tmp, "%Lo", &x); - return mk_number(ctx, x); - } else if (*name == 'd') { /* #d (decimal) */ - long long int x; - sscanf(&name[1], "%Ld", &x); - return mk_number(ctx, x); - } else if (*name == 'x') { /* #x (hex) */ - long long unsigned int x; - len = (len > 255) ? 255 : len - 1; - memcpy(tmp2, name + 1, len); - tmp2[len] = '\0'; - sprintf(tmp, "0x%s", tmp2); - sscanf(tmp, "%Lx", &x); - return mk_number(ctx, x); - } - } - return NIL; -} - -/* ========== Routines for Reading ========== */ - -#define TOK_LPAREN 0 -#define TOK_RPAREN 1 -#define TOK_DOT 2 -#define TOK_ATOM 3 -#define TOK_QUOTE 4 -#define TOK_COMMENT 5 -#define TOK_DQUOTE 6 -#define TOK_BQUOTE 7 -#define TOK_COMMA 8 -#define TOK_ATMARK 9 -#define TOK_SHARP 10 -#define TOK_EOS 11 -#define TOK_QUESTION 12 - -#define lparenp(c) ((c) == '(' || (c) == '[') -#define rparenp(c) ((c) == ')' || (c) == ']') - -/* read chacters to delimiter */ -inline static char -readstr(grn_ctx *ctx, char **str, unsigned int *size) -{ - char *start, *end; - for (start = end = ctx->impl->cur;;) { - unsigned int len; - /* null check and length check */ - if (!(len = grn_charlen(ctx, end, ctx->impl->str_end))) { - ctx->impl->cur = ctx->impl->str_end; - break; - } - if (grn_isspace(end, ctx->encoding) || - *end == ';' || lparenp(*end) || rparenp(*end)) { - ctx->impl->cur = end; - break; - } - end += len; - } - if (start < end || ctx->impl->cur < ctx->impl->str_end) { - *str = start; - *size = (unsigned int)(end - start); - return TOK_ATOM; - } else { - return TOK_EOS; - } -} - -/* read string expression "xxx...xxx" */ -inline static char -readstrexp(grn_ctx *ctx, char **str, unsigned int *size) -{ - char *start, *src, *dest; - for (start = src = dest = ctx->impl->cur;;) { - unsigned int len; - /* null check and length check */ - if (!(len = grn_charlen(ctx, src, ctx->impl->str_end))) { - ctx->impl->cur = ctx->impl->str_end; - if (start < dest) { - *str = start; - *size = (unsigned int)(dest - start); - return TOK_ATOM; - } - return TOK_EOS; - } - if (src[0] == '"' && len == 1) { - ctx->impl->cur = src + 1; - *str = start; - *size = (unsigned int)(dest - start); - return TOK_ATOM; - } else if (src[0] == '\\' && src + 1 < ctx->impl->str_end && len == 1) { - src++; - switch (*src) { - case 'n' : - *dest++ = '\n'; - break; - case 'r' : - *dest++ = '\r'; - break; - case 't' : - *dest++ = '\t'; - break; - default : - *dest++ = *src; - break; - } - src++; - } else { - while (len--) { *dest++ = *src++; } - } - } -} - -/* get token */ -inline static char -token(grn_ctx *ctx) -{ - SKIPSPACE(ctx->impl); - if (ctx->impl->cur >= ctx->impl->str_end) { return TOK_EOS; } - switch (*ctx->impl->cur) { - case '(': - case '[': - ctx->impl->cur++; - return TOK_LPAREN; - case ')': - case ']': - ctx->impl->cur++; - return TOK_RPAREN; - case '.': - ctx->impl->cur++; - if (ctx->impl->cur == ctx->impl->str_end || - grn_isspace(ctx->impl->cur, ctx->encoding) || - *ctx->impl->cur == ';' || lparenp(*ctx->impl->cur) || rparenp(*ctx->impl->cur)) { - return TOK_DOT; - } else { - ctx->impl->cur--; - return TOK_ATOM; - } - case '\'': - ctx->impl->cur++; - return TOK_QUOTE; - case ';': - ctx->impl->cur++; - return TOK_COMMENT; - case '"': - ctx->impl->cur++; - return TOK_DQUOTE; - case BACKQUOTE: - ctx->impl->cur++; - return TOK_BQUOTE; - case ',': - ctx->impl->cur++; - if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '@') { - ctx->impl->cur++; - return TOK_ATMARK; - } else { - return TOK_COMMA; - } - case '#': - ctx->impl->cur++; - return TOK_SHARP; - case '?': - ctx->impl->cur++; - return TOK_QUESTION; - default: - return TOK_ATOM; - } -} - -/* ========== Routines for Printing ========== */ -#define ok_abbrev(x) (PAIRP(x) && CDR(x) == NIL) - -void -grn_obj_inspect(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int flags) -{ - if (!obj) { - GRN_TEXT_PUTS(ctx, buf, "NULL"); - } else if (obj == NIL) { - GRN_TEXT_PUTS(ctx, buf, "()"); - } else if (obj == T) { - GRN_TEXT_PUTS(ctx, buf, "#t"); - } else if (obj == F) { - GRN_TEXT_PUTS(ctx, buf, "#f"); - } else { - if (SYMBOLP(obj)) { - char b[GRN_TABLE_MAX_KEY_SIZE + 1]; - symbol2str(obj, b); - if (flags & GRN_OBJ_INSPECT_SYMBOL_AS_STR) { - grn_text_esc(ctx, buf, (*b == ':') ? b + 1 : b, - strlen(b) - (*b == ':') ? 1 : 0); - } else { - GRN_TEXT_PUTS(ctx, buf, b); - } - return; - } - switch (obj->header.type) { - case GRN_VOID : - if (SYMBOLP(obj)) { - char b[GRN_TABLE_MAX_KEY_SIZE + 1]; - symbol2str(obj, b); - GRN_TEXT_PUTS(ctx, buf, b); - } else { - GRN_TEXT_PUTS(ctx, buf, "#<VOID>"); - } - break; - case GRN_CELL_OBJECT : - if (flags & GRN_OBJ_INSPECT_ESC) { - GRN_TEXT_PUTS(ctx, buf, "#p<"); - grn_text_itob(ctx, buf, obj->header.domain); - grn_text_itob(ctx, buf, obj->u.o.id); - GRN_TEXT_PUTC(ctx, buf, '>'); - } else { - grn_ql_obj_key(ctx, obj, buf); - } - break; - case GRN_SNIP : - case GRN_PATSNIP : - GRN_TEXT_PUTS(ctx, buf, "#<SNIP>"); - break; - case GRN_CELL_STR : - if (flags & GRN_OBJ_INSPECT_ESC) { - grn_text_esc(ctx, buf, STRVALUE(obj), STRSIZE(obj)); - } else { - grn_bulk_write(ctx, buf, STRVALUE(obj), STRSIZE(obj)); - } - break; - case GRN_CELL_INT : - grn_text_lltoa(ctx, buf, IVALUE(obj)); - break; - case GRN_CELL_FLOAT : - grn_text_ftoa(ctx, buf, FVALUE(obj)); - break; - case GRN_CELL_TIME : - GRN_TEXT_PUTS(ctx, buf, "#:<"); - grn_text_itoa(ctx, buf, obj->u.tv.tv_sec); - GRN_TEXT_PUTS(ctx, buf, "."); - grn_text_itoa(ctx, buf, obj->u.tv.tv_nsec); - GRN_TEXT_PUTC(ctx, buf, '>'); - break; - case GRN_QUERY : - GRN_TEXT_PUTS(ctx, buf, "#<QUERY>"); - break; - case GRN_VECTOR : - GRN_TEXT_PUTS(ctx, buf, "#<VECTOR>"); - break; - case GRN_UVECTOR : - GRN_TEXT_PUTS(ctx, buf, "#<UVECTOR>"); - break; - case GRN_CELL_OP : - GRN_TEXT_PUTS(ctx, buf, "#<OP>"); - break; - case GRN_CELL_SYNTAX : - GRN_TEXT_PUTS(ctx, buf, "#<SYNTAX>"); - break; - case GRN_CELL_PROC : - GRN_TEXT_PUTS(ctx, buf, "#<PROCEDURE "); - grn_text_itoa(ctx, buf, PROCNUM(obj)); - GRN_TEXT_PUTS(ctx, buf, ">"); - break; - case GRN_CELL_MACRO : - GRN_TEXT_PUTS(ctx, buf, "#<MACRO>"); - break; - case GRN_CELL_CLOSURE : - GRN_TEXT_PUTS(ctx, buf, "#<CLOSURE>"); - break; - case GRN_CELL_CONTINUATION : - GRN_TEXT_PUTS(ctx, buf, "#<CONTINUATION>"); - break; - case GRN_TYPE : - GRN_TEXT_PUTS(ctx, buf, "#<TYPE>"); - break; - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_NO_KEY : - case GRN_TABLE_PAT_KEY : - GRN_TEXT_PUTS(ctx, buf, "#<TABLE>"); - break; - case GRN_COLUMN_FIX_SIZE : - GRN_TEXT_PUTS(ctx, buf, "#<RA_COLUMN>"); - break; - case GRN_COLUMN_VAR_SIZE : - GRN_TEXT_PUTS(ctx, buf, "#<JA_COLUMN>"); - break; - case GRN_COLUMN_INDEX : - GRN_TEXT_PUTS(ctx, buf, "#<IDX_COLUMN>"); - break; - case GRN_CELL_LIST : - /* todo : detect loop */ - if (CAR(obj) == QUOTE && ok_abbrev(CDR(obj))) { - GRN_TEXT_PUTC(ctx, buf, '\''); - grn_obj_inspect(ctx, CADR(obj), buf, flags); - } else if (CAR(obj) == QQUOTE && ok_abbrev(CDR(obj))) { - GRN_TEXT_PUTC(ctx, buf, '`'); - grn_obj_inspect(ctx, CADR(obj), buf, flags); - } else if (CAR(obj) == UNQUOTE && ok_abbrev(CDR(obj))) { - GRN_TEXT_PUTC(ctx, buf, ','); - grn_obj_inspect(ctx, CADR(obj), buf, flags); - } else if (CAR(obj) == UNQUOTESP && ok_abbrev(CDR(obj))) { - GRN_TEXT_PUTS(ctx, buf, ",@"); - grn_obj_inspect(ctx, CADR(obj), buf, flags); - } else { - GRN_TEXT_PUTC(ctx, buf, '('); - for (;;) { - grn_obj_inspect(ctx, CAR(obj), buf, flags); - if ((obj = CDR(obj)) && (obj != NIL)) { - if (PAIRP(obj)) { - GRN_TEXT_PUTC(ctx, buf, ' '); - } else { - GRN_TEXT_PUTS(ctx, buf, " . "); - grn_obj_inspect(ctx, obj, buf, flags); - GRN_TEXT_PUTC(ctx, buf, ')'); - break; - } - } else { - GRN_TEXT_PUTC(ctx, buf, ')'); - break; - } - } - } - break; - default : - if (SYMBOLP(obj)) { - char b[GRN_TABLE_MAX_KEY_SIZE + 1]; - symbol2str(obj, b); - GRN_TEXT_PUTS(ctx, buf, b); - } else { - GRN_TEXT_PUTS(ctx, buf, "#<?("); - grn_text_itoa(ctx, buf, obj->header.type); - GRN_TEXT_PUTS(ctx, buf, ")?>"); - } - break; - } - } -} - -/* ========== Routines for Evaluation Cycle ========== */ - -/* make closure. c is code. e is environment */ -inline static grn_cell * -mk_closure(grn_ctx *ctx, grn_cell *c, grn_cell *e) -{ - grn_cell *x; - GET_CELL(ctx, c, e, x); - x->header.type = GRN_CELL_CLOSURE; - x->header.impl_flags = 0; - CAR(x) = c; - CDR(x) = e; - return x; -} - -/* make continuation. */ -inline static grn_cell * -mk_continuation(grn_ctx *ctx, grn_cell *d) -{ - grn_cell *x; - GET_CELL(ctx, NIL, d, x); - x->header.type = GRN_CELL_CONTINUATION; - x->header.impl_flags = 0; - CONT_DUMP(x) = d; - return x; -} - -/* reverse list -- make new cells */ -inline static grn_cell * -reverse(grn_ctx *ctx, grn_cell *a) /* a must be checked by gc */ -{ - grn_cell *p = NIL; - for ( ; PAIRP(a); a = CDR(a)) { - p = CONS(CAR(a), p); - if (ERRP(ctx, GRN_ERROR)) { return F; } - } - return p; -} - -/* reverse list --- no make new cells */ -inline static grn_cell * -non_alloc_rev(grn_cell *term, grn_cell *list) -{ - grn_cell *p = list, *result = term, *q; - while (p != NIL) { - q = CDR(p); - CDR(p) = result; - result = p; - p = q; - } - return result; -} - -/* append list -- make new cells */ -inline static grn_cell * -append(grn_ctx *ctx, grn_cell *a, grn_cell *b) -{ - grn_cell *p = b, *q; - if (a != NIL) { - a = reverse(ctx, a); - if (ERRP(ctx, GRN_ERROR)) { return F; } - while (a != NIL) { - q = CDR(a); - CDR(a) = p; - p = a; - a = q; - } - } - return p; -} - -/* equivalence of atoms */ -inline static int -eqv(grn_cell *a, grn_cell *b) -{ - if (a == b) { return 1; } - if (a->header.type != b->header.type) { return 0; } - switch (a->header.type) { - case GRN_CELL_OBJECT : - return (a->u.o.id == b->u.o.id && a->header.domain == b->header.domain); - break; - case GRN_CELL_STR : - return (a->u.b.size == b->u.b.size && - !memcmp(a->u.b.value, b->u.b.value, a->u.b.size)); - break; - case GRN_CELL_INT : - return (IVALUE(a) == IVALUE(b)); - break; - case GRN_CELL_FLOAT : - return !islessgreater(FVALUE(a), FVALUE(b)); - break; - case GRN_CELL_TIME : - return (!memcmp(&a->u.tv, &b->u.tv, sizeof(grn_timeval))); - break; - default : - /* todo : support other types */ - return 0; - break; - } -} - -/* expr (&) by int atoms */ -inline static int -logtest(grn_cell *a, grn_cell *b) -{ - if (a == b) { return 1; } - if (a->header.type != b->header.type) { return 0; } - switch (a->header.type) { - case GRN_CELL_INT : - return (IVALUE(a) & IVALUE(b) ? 1 : 0); - break; - default : - return 0; - break; - } -} -/* true or false value macro */ -#define istrue(p) ((p) != NIL && (p) != F) -#define isfalse(p) ((p) == F) - -/* control macros for Eval_Cycle */ -#define s_goto(ctx,a) do {\ - ctx->impl->op = (a);\ - return T;\ -} while (0) - -#define s_save(ctx,a,b,args) (\ - ctx->impl->dump = CONS(ctx->impl->envir, CONS((args), ctx->impl->dump)),\ - ctx->impl->dump = CONS((b), ctx->impl->dump),\ - ctx->impl->dump = CONS(mk_number(ctx, (int64_t)(a)), ctx->impl->dump)) - -#define s_return(ctx,a) do {\ - ctx->impl->value = (a);\ - ctx->impl->op = IVALUE(CAR(ctx->impl->dump));\ - ctx->impl->args = CADR(ctx->impl->dump);\ - ctx->impl->envir = CADDR(ctx->impl->dump);\ - ctx->impl->code = CADDDR(ctx->impl->dump);\ - ctx->impl->dump = CDDDDR(ctx->impl->dump);\ - return T;\ -} while (0) - -#define RTN_NIL_IF_HEAD(ctx) do {\ - if (((ctx)->impl->co.mode & GRN_CTX_HEAD)) { s_goto(ctx, OP_T0LVL); }\ -} while (0) - -#define RTN_NIL_IF_TAIL(ctx) do {\ - if (((ctx)->impl->co.mode & GRN_CTX_TAIL)) { s_return((ctx), NIL); } else { return NIL; }\ -} while (0) - -static grn_cell * -list_deep_copy(grn_ctx *ctx, grn_cell *c) { - /* NOTE: only list is copied */ - if (PAIRP(c)) { - /* TODO: convert recursion to loop */ - return CONS(list_deep_copy(ctx, CAR(c)), list_deep_copy(ctx, CDR(c))); - } else { - return c; - } -} - -static void -qquote_uquotelist(grn_ctx *ctx, grn_cell *cl, grn_cell *pcl, int level) { - /* reverse list */ - grn_cell *x, *y; - while (PAIRP(cl)) { - x = CAR(cl); - if (PAIRP(x)) { - y = CAR(x); - if (y == UNQUOTE) { - if (level) { - qquote_uquotelist(ctx, CDR(x), x, level - 1); - } else { - CDR(ctx->impl->args) = CONS(cl, CDR(ctx->impl->args)); /* save (unquote ...) cell */ - } - } else if (y == UNQUOTESP) { - if (level) { - qquote_uquotelist(ctx, CDR(x), x, level - 1); - } else { - CDR(ctx->impl->args) = CONS(pcl, CDR(ctx->impl->args)); /* save pre (unquote-splicing) cell */ - } - } else { - qquote_uquotelist(ctx, x, cl, level); - } - } else if (x == QQUOTE) { - qquote_uquotelist(ctx, CDR(cl), cl, level + 1); - return; - } - if (!level && CADR(cl) == UNQUOTE) { - CDR(ctx->impl->args) = CONS(cl, CDR(ctx->impl->args)); /* save (a . ,b) cell */ - return; - } - pcl = cl; - cl = CDR(cl); - } -} - -#define GC_THRESHOLD 1000000000 - -static grn_cell * -opexe(grn_ctx *ctx) -{ - register grn_cell *x, *y; - if (ctx->impl->op == OP_T0LVL || ctx->impl->n_entries > ctx->impl->ncells + GC_THRESHOLD) { - if (ctx->impl->gc_verbose) { - grn_obj buf; - GRN_TEXT_INIT(&buf, 0); - grn_obj_inspect(ctx, ctx->impl->envir, &buf, GRN_OBJ_INSPECT_ESC); - GRN_TEXT_PUTC(ctx, &buf, '\0'); - GRN_LOG(ctx, GRN_LOG_NOTICE, "mgc > ncells=%d envir=<%s>", ctx->impl->n_entries, GRN_TEXT_VALUE(&buf)); - GRN_OBJ_FIN(ctx, &buf); - } - grn_ctx_mgc(ctx); - if (ctx->impl->gc_verbose) { - GRN_LOG(ctx, GRN_LOG_NOTICE, "mgc < ncells=%d", ctx->impl->n_entries); - } - ctx->impl->ncells = ctx->impl->n_entries; - } - switch (ctx->impl->op) { - case OP_LOAD: /* load */ - if (BULKP(CAR(ctx->impl->args))) { - struct stat st; - char *fname = STRVALUE(CAR(ctx->impl->args)); - if (fname && !stat(fname, &st)) { - if (ctx->impl->inbuf) { GRN_FREE(ctx->impl->inbuf); } - if ((ctx->impl->inbuf = GRN_MALLOC(st.st_size))) { - int fd; - if ((fd = open(fname, O_RDONLY)) != -1) { - if (read(fd, ctx->impl->inbuf, st.st_size) == st.st_size) { - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "loading "); - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, STRVALUE(CAR(ctx->impl->args))); - ctx->impl->cur = ctx->impl->inbuf; - ctx->impl->str_end = ctx->impl->inbuf + st.st_size; - } - close(fd); - } - if (ctx->impl->cur != ctx->impl->inbuf) { - GRN_FREE(ctx->impl->inbuf); - ctx->impl->inbuf = NULL; - } - } - } - } - s_goto(ctx, OP_T0LVL); - - case OP_T0LVL: /* top level */ - ctx->impl->dump = NIL; - ctx->impl->envir = ctx->impl->global_env; - if (ctx->impl->batchmode) { - s_save(ctx, OP_T0LVL, NIL, NIL); - } else { - s_save(ctx, OP_VALUEPRINT, NIL, NIL); - } - s_save(ctx, OP_T1LVL, NIL, NIL); - ctx->impl->pht = &ctx->impl->phs; - *ctx->impl->pht = NIL; - s_goto(ctx, OP_READ); - - case OP_T1LVL: /* top level */ - // verbose check? - if (ctx->impl->phs != NIL && - !(ctx->impl->co.mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) { RTN_NIL_IF_TAIL(ctx); } - // GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n'); - ctx->impl->code = ctx->impl->value; - s_goto(ctx, OP_EVAL); - - case OP_READ: /* read */ - RTN_NIL_IF_HEAD(ctx); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - - case OP_VALUEPRINT: /* print evalution result */ - ctx->impl->args = ctx->impl->value; - s_save(ctx, OP_T0LVL, NIL, NIL); - grn_obj_inspect(ctx, ctx->impl->args, ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC); - s_return(ctx, T); - - case OP_EVAL: /* main part of evalution */ - // fixme : quick hack. - if (SYMBOLP(ctx->impl->code)) { /* symbol */ - if (keywordp(ctx->impl->code)) { s_return(ctx, ctx->impl->code); } - for (x = ctx->impl->envir; x != NIL; x = CDR(x)) { - for (y = CAR(x); y != NIL; y = CDR(y)) - if (CAAR(y) == ctx->impl->code) - break; - if (y != NIL) - break; - } - if (x != NIL) { - s_return(ctx, CDAR(y)); - } else { - if (PROCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); } - if (NATIVE_FUNCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); } - { - char buf[GRN_TABLE_MAX_KEY_SIZE + 1]; - symbol2str(ctx->impl->code, buf); - QLERR("Unbounded variable %s", buf); - } - } - } else if (PAIRP(ctx->impl->code)) { - if (SYNTAXP(x = CAR(ctx->impl->code))) { /* SYNTAX */ - ctx->impl->code = CDR(ctx->impl->code); - s_goto(ctx, SYNTAXNUM(x)); - } else {/* first, eval top element and eval arguments */ - s_save(ctx, OP_E0ARGS, NIL, ctx->impl->code); - ctx->impl->code = CAR(ctx->impl->code); - // if (NATIVE_FUNCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); } /* call native funcs. fast */ - s_goto(ctx, OP_EVAL); - } - } else { - s_return(ctx, ctx->impl->code); - } - - case OP_E0ARGS: /* eval arguments */ - if (MACROP(ctx->impl->value)) { /* macro expansion */ - s_save(ctx, OP_DOMACRO, NIL, NIL); - ctx->impl->args = CONS(ctx->impl->code, NIL); - ctx->impl->code = ctx->impl->value; - s_goto(ctx, OP_APPLY); - } else { - ctx->impl->code = CDR(ctx->impl->code); - s_goto(ctx, OP_E1ARGS); - } - - case OP_E1ARGS: /* eval arguments */ - ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args); - if (PAIRP(ctx->impl->code)) { /* continue */ - s_save(ctx, OP_E1ARGS, ctx->impl->args, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - ctx->impl->args = NIL; - s_goto(ctx, OP_EVAL); - } else { /* end */ - ctx->impl->args = reverse(ctx, ctx->impl->args); - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = CDR(ctx->impl->args); - s_goto(ctx, OP_APPLY); - } - - case OP_APPLY: /* apply 'code' to 'args' */ - if (NATIVE_FUNCP(ctx->impl->code)) { - ctx->impl->dump = CONS(ctx->impl->code, ctx->impl->dump); - ctx->impl->co.func = ctx->impl->code->u.o.func; - s_goto(ctx, OP_NATIVE); - } else if (PROCP(ctx->impl->code)) { - s_goto(ctx, PROCNUM(ctx->impl->code)); /* PROCEDURE */ - } else if (CLOSUREP(ctx->impl->code)) { /* CLOSURE */ - /* make environment */ - ctx->impl->envir = CONS(NIL, CLOSURE_ENV(ctx->impl->code)); - for (x = CAR(CLOSURE_CODE(ctx->impl->code)), y = ctx->impl->args; - PAIRP(x); x = CDR(x), y = CDR(y)) { - if (y == NIL) { - QLERR("Few arguments"); - } else { - CAR(ctx->impl->envir) = CONS(CONS(CAR(x), CAR(y)), CAR(ctx->impl->envir)); - } - } - if (x == NIL) { - /*-- - * if (y != NIL) { - * QLERR("Many arguments"); - * } - */ - } else if (SYMBOLP(x)) - CAR(ctx->impl->envir) = CONS(CONS(x, y), CAR(ctx->impl->envir)); - else { - QLERR("Syntax error in closure"); - } - ctx->impl->code = CDR(CLOSURE_CODE(ctx->impl->code)); - ctx->impl->args = NIL; - s_goto(ctx, OP_BEGIN); - } else if (CONTINUATIONP(ctx->impl->code)) { /* CONTINUATION */ - ctx->impl->dump = CONT_DUMP(ctx->impl->code); - s_return(ctx, ctx->impl->args != NIL ? CAR(ctx->impl->args) : NIL); - } else { - QLERR("Illegal function"); - } - - case OP_DOMACRO: /* do macro */ - ctx->impl->code = ctx->impl->value; - s_goto(ctx, OP_EVAL); - - case OP_LAMBDA: /* lambda */ - s_return(ctx, mk_closure(ctx, ctx->impl->code, ctx->impl->envir)); - - case OP_QUOTE: /* quote */ - s_return(ctx, CAR(ctx->impl->code)); - - case OP_DEF0: /* define */ - if (PAIRP(CAR(ctx->impl->code))) { - x = CAAR(ctx->impl->code); - ctx->impl->code = CONS(LAMBDA, CONS(CDAR(ctx->impl->code), CDR(ctx->impl->code))); - } else { - x = CAR(ctx->impl->code); - ctx->impl->code = CADR(ctx->impl->code); - } - if (!SYMBOLP(x)) { - QLERR("Variable is not symbol"); - } - s_save(ctx, OP_DEF1, NIL, x); - s_goto(ctx, OP_EVAL); - - case OP_DEF1: /* define */ - for (x = CAR(ctx->impl->envir); x != NIL; x = CDR(x)) - if (CAAR(x) == ctx->impl->code) - break; - if (x != NIL) - CDAR(x) = ctx->impl->value; - else - CAR(ctx->impl->envir) = CONS(CONS(ctx->impl->code, ctx->impl->value), CAR(ctx->impl->envir)); - s_return(ctx, ctx->impl->code); - - case OP_SET0: /* set! */ - s_save(ctx, OP_SET1, NIL, CAR(ctx->impl->code)); - ctx->impl->code = CADR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_SET1: /* set! */ - for (x = ctx->impl->envir; x != NIL; x = CDR(x)) { - for (y = CAR(x); y != NIL; y = CDR(y)) - if (CAAR(y) == ctx->impl->code) - break; - if (y != NIL) - break; - } - if (x != NIL) { - CDAR(y) = ctx->impl->value; - s_return(ctx, ctx->impl->value); - } else { - if (SYMBOLP(ctx->impl->code)) { - char buf[GRN_TABLE_MAX_KEY_SIZE + 1]; - symbol2str(ctx->impl->code, buf); - QLERR("Unbounded variable %s", buf); - } else { - QLERR("Unbounded variable"); - } - } - - case OP_BEGIN: /* begin */ - if (!PAIRP(ctx->impl->code)) { - s_return(ctx, ctx->impl->code); - } - if (CDR(ctx->impl->code) != NIL) { - s_save(ctx, OP_BEGIN, NIL, CDR(ctx->impl->code)); - } - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_IF0: /* if */ - s_save(ctx, OP_IF1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_IF1: /* if */ - if (istrue(ctx->impl->value)) - ctx->impl->code = CAR(ctx->impl->code); - else - ctx->impl->code = CADR(ctx->impl->code); /* (if #f 1) ==> () because - * CAR(NIL) = NIL */ - s_goto(ctx, OP_EVAL); - - case OP_LET0: /* let */ - ctx->impl->args = NIL; - ctx->impl->value = ctx->impl->code; - ctx->impl->code = SYMBOLP(CAR(ctx->impl->code)) ? CADR(ctx->impl->code) : CAR(ctx->impl->code); - s_goto(ctx, OP_LET1); - - case OP_LET1: /* let (caluculate parameters) */ - ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args); - if (PAIRP(ctx->impl->code)) { /* continue */ - QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code))); - s_save(ctx, OP_LET1, ctx->impl->args, CDR(ctx->impl->code)); - ctx->impl->code = CADAR(ctx->impl->code); - ctx->impl->args = NIL; - s_goto(ctx, OP_EVAL); - } else { /* end */ - ctx->impl->args = reverse(ctx, ctx->impl->args); - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = CDR(ctx->impl->args); - s_goto(ctx, OP_LET2); - } - - case OP_LET2: /* let */ - ctx->impl->envir = CONS(NIL, ctx->impl->envir); - for (x = SYMBOLP(CAR(ctx->impl->code)) ? CADR(ctx->impl->code) : CAR(ctx->impl->code), y = ctx->impl->args; - y != NIL; x = CDR(x), y = CDR(y)) - CAR(ctx->impl->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->impl->envir)); - if (SYMBOLP(CAR(ctx->impl->code))) { /* named let */ - for (x = CADR(ctx->impl->code), ctx->impl->args = NIL; PAIRP(x); x = CDR(x)) - ctx->impl->args = CONS(CAAR(x), ctx->impl->args); - x = mk_closure(ctx, CONS(reverse(ctx, ctx->impl->args), CDDR(ctx->impl->code)), - ctx->impl->envir); - CAR(ctx->impl->envir) = CONS(CONS(CAR(ctx->impl->code), x), CAR(ctx->impl->envir)); - ctx->impl->code = CDDR(ctx->impl->code); - ctx->impl->args = NIL; - } else { - ctx->impl->code = CDR(ctx->impl->code); - ctx->impl->args = NIL; - } - s_goto(ctx, OP_BEGIN); - - case OP_LET0AST: /* let* */ - if (CAR(ctx->impl->code) == NIL) { - ctx->impl->envir = CONS(NIL, ctx->impl->envir); - ctx->impl->code = CDR(ctx->impl->code); - s_goto(ctx, OP_BEGIN); - } - s_save(ctx, OP_LET1AST, CDR(ctx->impl->code), CAR(ctx->impl->code)); - QLASSERT(LISTP(CAR(ctx->impl->code)) && - LISTP(CAAR(ctx->impl->code)) && LISTP((CDR(CAAR(ctx->impl->code))))); - ctx->impl->code = CADAAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_LET1AST: /* let* (make new frame) */ - ctx->impl->envir = CONS(NIL, ctx->impl->envir); - s_goto(ctx, OP_LET2AST); - - case OP_LET2AST: /* let* (caluculate parameters) */ - CAR(ctx->impl->envir) = CONS(CONS(CAAR(ctx->impl->code), ctx->impl->value), CAR(ctx->impl->envir)); - ctx->impl->code = CDR(ctx->impl->code); - if (PAIRP(ctx->impl->code)) { /* continue */ - QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code))); - s_save(ctx, OP_LET2AST, ctx->impl->args, ctx->impl->code); - ctx->impl->code = CADAR(ctx->impl->code); - ctx->impl->args = NIL; - s_goto(ctx, OP_EVAL); - } else { /* end */ - ctx->impl->code = ctx->impl->args; - ctx->impl->args = NIL; - s_goto(ctx, OP_BEGIN); - } - - case OP_LET0REC: /* letrec */ - ctx->impl->envir = CONS(NIL, ctx->impl->envir); - ctx->impl->args = NIL; - ctx->impl->value = ctx->impl->code; - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_LET1REC); - - case OP_LET1REC: /* letrec (caluculate parameters) */ - ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args); - if (PAIRP(ctx->impl->code)) { /* continue */ - QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code))); - s_save(ctx, OP_LET1REC, ctx->impl->args, CDR(ctx->impl->code)); - ctx->impl->code = CADAR(ctx->impl->code); - ctx->impl->args = NIL; - s_goto(ctx, OP_EVAL); - } else { /* end */ - ctx->impl->args = reverse(ctx, ctx->impl->args); - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = CDR(ctx->impl->args); - s_goto(ctx, OP_LET2REC); - } - - case OP_LET2REC: /* letrec */ - for (x = CAR(ctx->impl->code), y = ctx->impl->args; y != NIL; x = CDR(x), y = CDR(y)) - CAR(ctx->impl->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->impl->envir)); - ctx->impl->code = CDR(ctx->impl->code); - ctx->impl->args = NIL; - s_goto(ctx, OP_BEGIN); - - case OP_COND0: /* cond */ - if (!PAIRP(ctx->impl->code)) { - QLERR("Syntax error in cond"); - } - s_save(ctx, OP_COND1, NIL, ctx->impl->code); - ctx->impl->code = CAAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_COND1: /* cond */ - if (istrue(ctx->impl->value)) { - if ((ctx->impl->code = CDAR(ctx->impl->code)) == NIL) { - s_return(ctx, ctx->impl->value); - } - s_goto(ctx, OP_BEGIN); - } else { - if ((ctx->impl->code = CDR(ctx->impl->code)) == NIL) { - s_return(ctx, NIL); - } else { - s_save(ctx, OP_COND1, NIL, ctx->impl->code); - ctx->impl->code = CAAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - } - } - - case OP_DELAY: /* delay */ - x = mk_closure(ctx, CONS(NIL, ctx->impl->code), ctx->impl->envir); - if (ERRP(ctx, GRN_ERROR)) { return F; } - SETPROMISE(x); - s_return(ctx, x); - - case OP_AND0: /* and */ - if (ctx->impl->code == NIL) { - s_return(ctx, T); - } - s_save(ctx, OP_AND1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_AND1: /* and */ - if (isfalse(ctx->impl->value)) { - s_return(ctx, ctx->impl->value); - } else if (ctx->impl->code == NIL) { - s_return(ctx, ctx->impl->value); - } else { - s_save(ctx, OP_AND1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - } - - case OP_OR0: /* or */ - if (ctx->impl->code == NIL) { - s_return(ctx, F); - } - s_save(ctx, OP_OR1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_OR1: /* or */ - if (istrue(ctx->impl->value)) { - s_return(ctx, ctx->impl->value); - } else if (ctx->impl->code == NIL) { - s_return(ctx, ctx->impl->value); - } else { - s_save(ctx, OP_OR1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - } - - case OP_C0STREAM: /* cons-stream */ - s_save(ctx, OP_C1STREAM, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_C1STREAM: /* cons-stream */ - ctx->impl->args = ctx->impl->value; /* save ctx->impl->value to register ctx->impl->args for gc */ - x = mk_closure(ctx, CONS(NIL, ctx->impl->code), ctx->impl->envir); - if (ERRP(ctx, GRN_ERROR)) { return F; } - SETPROMISE(x); - s_return(ctx, CONS(ctx->impl->args, x)); - - case OP_0MACRO: /* macro */ - x = CAR(ctx->impl->code); - ctx->impl->code = CADR(ctx->impl->code); - if (!SYMBOLP(x)) { - QLERR("Variable is not symbol"); - } - s_save(ctx, OP_1MACRO, NIL, x); - s_goto(ctx, OP_EVAL); - - case OP_1MACRO: /* macro */ - ctx->impl->value->header.type = GRN_CELL_MACRO; - for (x = CAR(ctx->impl->envir); x != NIL; x = CDR(x)) - if (CAAR(x) == ctx->impl->code) - break; - if (x != NIL) - CDAR(x) = ctx->impl->value; - else - CAR(ctx->impl->envir) = CONS(CONS(ctx->impl->code, ctx->impl->value), CAR(ctx->impl->envir)); - s_return(ctx, ctx->impl->code); - - case OP_CASE0: /* case */ - s_save(ctx, OP_CASE1, NIL, CDR(ctx->impl->code)); - ctx->impl->code = CAR(ctx->impl->code); - s_goto(ctx, OP_EVAL); - - case OP_CASE1: /* case */ - for (x = ctx->impl->code; x != NIL; x = CDR(x)) { - if (!PAIRP(y = CAAR(x))) - break; - for ( ; y != NIL; y = CDR(y)) - if (eqv(CAR(y), ctx->impl->value)) - break; - if (y != NIL) - break; - } - if (x != NIL) { - if (PAIRP(CAAR(x))) { - ctx->impl->code = CDAR(x); - s_goto(ctx, OP_BEGIN); - } else {/* else */ - s_save(ctx, OP_CASE2, NIL, CDAR(x)); - ctx->impl->code = CAAR(x); - s_goto(ctx, OP_EVAL); - } - } else { - s_return(ctx, NIL); - } - - case OP_CASE2: /* case */ - if (istrue(ctx->impl->value)) { - s_goto(ctx, OP_BEGIN); - } else { - s_return(ctx, NIL); - } - case OP_PAPPLY: /* apply */ - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = CADR(ctx->impl->args); - s_goto(ctx, OP_APPLY); - - case OP_PEVAL: /* eval */ - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = NIL; - s_goto(ctx, OP_EVAL); - - case OP_CONTINUATION: /* call-with-current-continuation */ - ctx->impl->code = CAR(ctx->impl->args); - ctx->impl->args = CONS(mk_continuation(ctx, ctx->impl->dump), NIL); - s_goto(ctx, OP_APPLY); - - case OP_SETCAR: /* set-car! */ - if (PAIRP(CAR(ctx->impl->args))) { - CAAR(ctx->impl->args) = CADR(ctx->impl->args); - s_return(ctx, CAR(ctx->impl->args)); - } else { - QLERR("Unable to set-car! for non-cons cell"); - } - - case OP_SETCDR: /* set-cdr! */ - if (PAIRP(CAR(ctx->impl->args))) { - CDAR(ctx->impl->args) = CADR(ctx->impl->args); - s_return(ctx, CAR(ctx->impl->args)); - } else { - QLERR("Unable to set-cdr! for non-cons cell"); - } - - case OP_FORCE: /* force */ - ctx->impl->code = CAR(ctx->impl->args); - if (PROMISEP(ctx->impl->code)) { - ctx->impl->args = NIL; - s_goto(ctx, OP_APPLY); - } else { - s_return(ctx, ctx->impl->code); - } - - case OP_ERR0: /* error */ - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "*** ERROR: "); - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, ctx->errbuf); - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n'); - ctx->impl->args = NIL; - s_goto(ctx, OP_T0LVL); - - case OP_ERR1: /* error */ - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "*** ERROR:"); - while (ctx->impl->args != NIL) { - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, ' '); - grn_obj_inspect(ctx, CAR(ctx->impl->args), ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC); - ctx->impl->args = CDR(ctx->impl->args); - } - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n'); - s_goto(ctx, OP_T0LVL); - - case OP_PUT: /* put */ - if (!HASPROP(CAR(ctx->impl->args)) || !HASPROP(CADR(ctx->impl->args))) { - QLERR("Illegal use of put"); - } - for (x = SYMPROP(CAR(ctx->impl->args)), y = CADR(ctx->impl->args); x != NIL; x = CDR(x)) - if (CAAR(x) == y) - break; - if (x != NIL) - CDAR(x) = CADDR(ctx->impl->args); - else - SYMPROP(CAR(ctx->impl->args)) = CONS(CONS(y, CADDR(ctx->impl->args)), - SYMPROP(CAR(ctx->impl->args))); - s_return(ctx, T); - - case OP_GET: /* get */ - if (!HASPROP(CAR(ctx->impl->args)) || !HASPROP(CADR(ctx->impl->args))) { - QLERR("Illegal use of get"); - } - for (x = SYMPROP(CAR(ctx->impl->args)), y = CADR(ctx->impl->args); x != NIL; x = CDR(x)) - if (CAAR(x) == y) - break; - if (x != NIL) { - s_return(ctx, CDAR(x)); - } else { - s_return(ctx, NIL); - } - - case OP_SDOWN: /* shutdown */ - GRN_LOG(ctx, GRN_LOG_NOTICE, "shutting down.."); - grn_gctx.stat = GRN_CTX_QUIT; - s_goto(ctx, OP_QUIT); - - case OP_RDSEXPR: - { - char tok, *str; - unsigned int len; - RTN_NIL_IF_HEAD(ctx); - switch (ctx->impl->tok) { - case TOK_COMMENT: - skipline(ctx); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_LPAREN: - if ((tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - ctx->impl->tok = tok; - if (ctx->impl->tok == TOK_RPAREN) { - s_return(ctx, NIL); - } else if (ctx->impl->tok == TOK_DOT) { - QLERR("syntax error: illegal dot expression"); - } else { - s_save(ctx, OP_RDLIST, NIL, NIL); - s_goto(ctx, OP_RDSEXPR); - } - case TOK_QUOTE: - s_save(ctx, OP_RDQUOTE, NIL, NIL); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_BQUOTE: - s_save(ctx, OP_RDQQUOTE, NIL, NIL); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_COMMA: - s_save(ctx, OP_RDUNQUOTE, NIL, NIL); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_ATMARK: - s_save(ctx, OP_RDUQTSP, NIL, NIL); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_ATOM: - if (readstr(ctx, &str, &len) == TOK_EOS) { ctx->impl->tok = TOK_EOS; RTN_NIL_IF_TAIL(ctx); } - s_return(ctx, mk_atom(ctx, str, len, NIL)); - case TOK_DQUOTE: - if (readstrexp(ctx, &str, &len) == TOK_EOS) { - QLERR("unterminated string"); - } - s_return(ctx, grn_ql_mk_string(ctx, str, len)); - case TOK_SHARP: - if ((readstr(ctx, &str, &len) == TOK_EOS) || - (x = mk_const(ctx, str, len)) == NIL) { - QLERR("Undefined sharp expression"); - } else { - s_return(ctx, x); - } - case TOK_EOS : - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - s_goto(ctx, OP_RDSEXPR); - case TOK_QUESTION: - { - grn_cell *o, *p; - GRN_CELL_NEW(ctx, o); - p = CONS(o, NIL); - o->header.type = GRN_CELL_STR; - o->header.impl_flags = 0; - o->u.b.size = 1; - o->u.b.value = (char *)"?"; - *ctx->impl->pht = p; - ctx->impl->pht = &CDR(p); - s_return(ctx, o); - } - default: - QLERR("syntax error: illegal token"); - } - } - break; - - case OP_RDLIST: - RTN_NIL_IF_HEAD(ctx); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - if (ctx->impl->tok == TOK_COMMENT) { - skipline(ctx); - s_goto(ctx, OP_RDLIST); - } - ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args); - if (ctx->impl->tok == TOK_RPAREN) { - grn_cell *v = non_alloc_rev(NIL, ctx->impl->args); - if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '.') { - char *str = NULL; - unsigned int len = 0; - if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ } - s_return(ctx, mk_atom(ctx, str, len, v)); - } else { - s_return(ctx, v); - } - } else if (ctx->impl->tok == TOK_DOT) { - s_save(ctx, OP_RDDOT, ctx->impl->args, NIL); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { - ctx->impl->op = OP_RDSEXPR; RTN_NIL_IF_TAIL(ctx); - } - s_goto(ctx, OP_RDSEXPR); - } else { - s_save(ctx, OP_RDLIST, ctx->impl->args, NIL);; - s_goto(ctx, OP_RDSEXPR); - } - - case OP_RDDOT: - RTN_NIL_IF_HEAD(ctx); - if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); } - if (ctx->impl->tok != TOK_RPAREN) { - QLERR("syntax error: illegal dot expression"); - } else { - grn_cell *v = non_alloc_rev(ctx->impl->value, ctx->impl->args); - if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '.') { - char *str = NULL; - unsigned int len = 0; - if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ } - s_return(ctx, mk_atom(ctx, str, len, v)); - } else { - s_return(ctx, v); - } - } - - case OP_RDQUOTE: - s_return(ctx, CONS(QUOTE, CONS(ctx->impl->value, NIL))); - - case OP_RDQQUOTE: - s_return(ctx, CONS(QQUOTE, CONS(ctx->impl->value, NIL))); - - case OP_RDUNQUOTE: - s_return(ctx, CONS(UNQUOTE, CONS(ctx->impl->value, NIL))); - - case OP_RDUQTSP: - s_return(ctx, CONS(UNQUOTESP, CONS(ctx->impl->value, NIL))); - - case OP_NATIVE: - ctx->impl->dump = CDR(ctx->impl->dump); - s_return(ctx, ctx->impl->value); - case OP_QQUOTE0: - ctx->impl->code = list_deep_copy(ctx, ctx->impl->code); - ctx->impl->args = CONS(ctx->impl->code, NIL); - qquote_uquotelist(ctx, ctx->impl->code, ctx->impl->code, 0); - ctx->impl->code = CDR(ctx->impl->args); - s_goto(ctx, OP_QQUOTE1); - case OP_QQUOTE1: - while (PAIRP(ctx->impl->code)) { - x = CAR(ctx->impl->code); - if (PAIRP(x) && LISTP(CDR(x))) { - s_save(ctx, OP_QQUOTE2, ctx->impl->args, ctx->impl->code); - y = CADR(x); - if (y == UNQUOTE) { - QLASSERT(LISTP(CDDR(x))); - ctx->impl->code = CADDR(x); - } else if (CAR(y) == UNQUOTESP) { - QLASSERT(LISTP(CDR(y))); - ctx->impl->code = CADR(y); - } else { - y = CAR(x); - if (CAR(y) == UNQUOTE) { - ctx->impl->code = CADR(y); - } else if (CAAR(y) == UNQUOTESP) { - ctx->impl->code = CADAR(y); - } else { - /* error */ - } - } - s_goto(ctx, OP_EVAL); - } - ctx->impl->code = CDR(ctx->impl->code); - } - s_return(ctx, CAAR(ctx->impl->args)); - case OP_QQUOTE2: - x = CAR(ctx->impl->code); - if (x) { - y = CADR(x); - if (y == UNQUOTE) { - CDR(x) = ctx->impl->value; - } else if (CAR(y) == UNQUOTESP) { - if (ctx->impl->value == NIL) { - CDR(x) = CDDR(x); - } else if (!PAIRP(ctx->impl->value) ) { - /* error */ - } else { - ctx->impl->value = list_deep_copy(ctx, ctx->impl->value); - for (y = ctx->impl->value; CDR(y) != NIL; y = CDR(y)) {} - CDR(y) = CDDR(x); - CDR(x) = ctx->impl->value; - } - } else { - y = CAAR(x); - if (y == UNQUOTE) { - CAR(x) = ctx->impl->value; - } else if (CAR(y) == UNQUOTESP) { - if (ctx->impl->value == NIL) { - CAR(x) = CDAR(x); - } else if (!PAIRP(ctx->impl->value) ) { - /* error */ - } else { - ctx->impl->value = list_deep_copy(ctx, ctx->impl->value); - for (y = ctx->impl->value; CDR(y) != NIL; y = CDR(y)) {} - CDR(y) = CDAR(x); - CAR(x) = ctx->impl->value; - } - } else { - /* error */ - } - } - ctx->impl->code = CDR(ctx->impl->code); - s_goto(ctx, OP_QQUOTE1); - } else { - /* error */ - } - } - GRN_LOG(ctx, GRN_LOG_ERROR, "illegal op (%d)", ctx->impl->op); - return NIL; -} - -/* kernel of this intepreter */ -inline static void -Eval_Cycle(grn_ctx *ctx) -{ - ctx->impl->co.func = NULL; - ctx->impl->co.last = 0; - while (opexe(ctx) != NIL) { - switch (ctx->impl->op) { - case OP_NATIVE : - ctx->stat = GRN_QL_NATIVE; - return; - case OP_T0LVL : - ctx->stat = GRN_QL_TOPLEVEL; - return; - case OP_T1LVL : - ctx->stat = (ctx->impl->phs != NIL) ? GRN_QL_WAIT_ARG : GRN_QL_EVAL; - return; - case OP_QUIT : - ctx->stat = GRN_CTX_QUITTING; - return; - default : - break; - } - if (ERRP(ctx, GRN_ERROR)) { return; } - } - ctx->stat = GRN_QL_WAIT_EXPR; -} - -grn_cell * -grn_ql_eval(grn_ctx *ctx, grn_cell *code, grn_cell *objs) -{ - grn_ql_co co; - uint8_t op = ctx->impl->op; - uint8_t stat = ctx->stat; - uint8_t feed_mode = ctx->impl->feed_mode; - grn_cell *o, *code_ = ctx->impl->code; - o = CONS(objs, ctx->impl->envir); - memcpy(&co, &ctx->impl->co, sizeof(grn_ql_co)); - s_save(ctx, OP_QUIT, ctx->impl->args, o); - ctx->impl->op = OP_EVAL; - ctx->stat = GRN_QL_EVAL; - ctx->impl->code = code; - ctx->impl->feed_mode = grn_ql_atonce; - grn_ql_feed(ctx, NULL, 0, 0); - ctx->impl->feed_mode = feed_mode; - ctx->stat = stat; - ctx->impl->op = op; - ctx->impl->envir = CDR(o); - ctx->impl->code = code_; - memcpy(&ctx->impl->co, &co, sizeof(grn_ql_co)); - return ctx->impl->value; -} - -/* ========== native functions ========== */ - -#define s_retbool(tf) do { return (tf) ? T : F; } while (0) - -#define do_op(x,y,op) do {\ - switch ((x)->header.type) {\ - case GRN_CELL_INT :\ - switch ((y)->header.type) {\ - case GRN_CELL_INT :\ - IVALUE(x) = IVALUE(x) op IVALUE(y);\ - break;\ - case GRN_CELL_FLOAT :\ - SETFLOAT(x, ((double) IVALUE(x)) op FVALUE(y));\ - break;\ - default :\ - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\ - IVALUE(x) = IVALUE(x) op IVALUE(y);\ - }\ - break;\ - case GRN_CELL_FLOAT :\ - switch ((y)->header.type) {\ - case GRN_CELL_INT :\ - FVALUE(x) = FVALUE(x) op IVALUE(y);\ - break;\ - case GRN_CELL_FLOAT :\ - FVALUE(x) = FVALUE(x) op FVALUE(y);\ - break;\ - default :\ - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\ - FVALUE(x) = FVALUE(x) op IVALUE(y);\ - }\ - break;\ - default :\ - QLERR("can't convert into numeric");\ - }\ -} while (0) - -#define do_compare(x,y,r,op) do {\ - switch (x->header.type) {\ - case GRN_CELL_INT :\ - switch (y->header.type) {\ - case GRN_CELL_INT :\ - r = (IVALUE(x) op IVALUE(y));\ - break;\ - case GRN_CELL_FLOAT :\ - r = (IVALUE(x) op FVALUE(y));\ - break;\ - default :\ - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\ - r = (IVALUE(x) op IVALUE(y));\ - }\ - break;\ - case GRN_CELL_FLOAT :\ - switch (y->header.type) {\ - case GRN_CELL_INT :\ - r = (FVALUE(x) op IVALUE(y));\ - break;\ - case GRN_CELL_FLOAT :\ - r = (FVALUE(x) op FVALUE(y));\ - break;\ - default :\ - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\ - r = (FVALUE(x) op IVALUE(y));\ - }\ - break;\ - case GRN_CELL_STR :\ - if (y->header.type == GRN_CELL_STR) {\ - int r_;\ - uint32_t la = x->u.b.size, lb = y->u.b.size;\ - if (la > lb) {\ - if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) {\ - r_ = 1;\ - }\ - } else {\ - if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) {\ - r_ = la == lb ? 0 : -1;\ - }\ - }\ - r = (r_ op 0);\ - } else {\ - QLERR("can't compare");\ - }\ - break;\ - case GRN_CELL_TIME :\ - if (y->header.type == GRN_CELL_TIME) {\ - if (x->u.tv.tv_sec != y->u.tv.tv_sec) {\ - r = (x->u.tv.tv_sec op y->u.tv.tv_sec);\ - } else {\ - r = (x->u.tv.tv_nsec op y->u.tv.tv_nsec);\ - }\ - } else {\ - QLERR("can't compare");\ - }\ - break;\ - default :\ - r = (memcmp(&x->u.tv, &y->u.tv, sizeof(grn_timeval)) op 0);\ - }\ -} while (0) - -#define time_op(x,y,v,op) {\ - switch (y->header.type) {\ - case GRN_CELL_TIME :\ - {\ - double dv= x->u.tv.tv_sec op y->u.tv.tv_sec;\ - dv += (x->u.tv.tv_nsec op y->u.tv.tv_nsec) / GRN_TIME_NSEC_PER_SEC_F;\ - SETFLOAT(v, dv);\ - }\ - break;\ - case GRN_CELL_INT :\ - {\ - grn_timeval tv;\ - int64_t sec = x->u.tv.tv_sec op IVALUE(y);\ - if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\ - tv.tv_sec = (int)sec;\ - tv.tv_nsec = x->u.tv.tv_nsec;\ - SETTIME(v, &tv);\ - }\ - break;\ - case GRN_CELL_FLOAT :\ - {\ - grn_timeval tv;\ - double sec = x->u.tv.tv_sec op (int)FVALUE(y);\ - int32_t nsec = x->u.tv.tv_nsec op (int)((FVALUE(y) - (int)FVALUE(y)) * GRN_TIME_NSEC_PER_SEC);\ - if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\ - tv.tv_sec = (int)sec;\ - if (nsec < 0) {\ - tv.tv_sec--;\ - nsec += GRN_TIME_NSEC_PER_SEC;\ - } else if (nsec >= GRN_TIME_NSEC_PER_SEC) {\ - tv.tv_sec++;\ - nsec -= GRN_TIME_NSEC_PER_SEC;\ - }\ - tv.tv_nsec = nsec;\ - SETTIME(v, &tv);\ - }\ - break;\ - default :\ - QLERR("can't convert into numeric value");\ - break;\ - }\ -} while (0) - -static grn_cell * -nf_add(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *x, *v; - if (!PAIRP(args)) { QLERR("list required"); } - switch (CAR(args)->header.type) { - case GRN_CELL_STR : - { - grn_obj buf; - GRN_TEXT_INIT(&buf, 0); - while (PAIRP(args)) { - POP(x, args); - grn_obj_inspect(ctx, x, &buf, 0); - } - GRN_STR2OBJ(ctx, &buf, v); - } - break; - case GRN_CELL_TIME : - if (PAIRP(CDR(args)) && NUMBERP(CADR(args))) { - GRN_CELL_NEW(ctx, v); - time_op(CAR(args), CADR(args), v, +); - } else { - QLERR("can't convert into numeric value"); - } - break; - default : - v = mk_number(ctx, 0); - while (PAIRP(args)) { - POP(x, args); - do_op(v, x, +); - } - break; - } - return v; -} - -static grn_cell * -nf_sub(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *v = mk_number(ctx, 0); - register grn_cell *x; - if (PAIRP(args) && CDR(args) != NIL) { - if (CAR(args)->header.type == GRN_CELL_TIME) { - time_op(CAR(args), CADR(args), v, -); - return v; - } - POP(x, args); - do_op(v, x, +); - } - while (PAIRP(args)) { - POP(x, args); - do_op(v, x, -); - } - return v; -} - -static grn_cell * -nf_mul(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *v, *x; - if (CAR(args)->header.type == GRN_CELL_STR && CADR(args)->header.type == GRN_CELL_INT) { - int i, n = (int)IVALUE(CADR(args)); - grn_obj buf; - GRN_TEXT_INIT(&buf, 0); - POP(x, args); - for (i = 0; i < n; i++) { - grn_obj_inspect(ctx, x, &buf, 0); - } - GRN_STR2OBJ(ctx, &buf, v); - } else { - v = mk_number(ctx, 1); - while (PAIRP(args)) { - POP(x, args); - do_op(v, x, *); - } - } - return v; -} - -static grn_cell * -nf_div(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *v; - register grn_cell *x; - if (PAIRP(args) && CDR(args) != NIL) { - v = mk_number(ctx, 0); - POP(x, args); - do_op(v, x, +); - } else { - v = mk_number(ctx, 1); - } - while (PAIRP(args)) { - POP(x, args); - if (x->header.type == GRN_CELL_INT && IVALUE(x) == 0 && v->header.type == GRN_CELL_INT) { - SETFLOAT(v, (double)IVALUE(v)); - } - do_op(v, x, /); - } - return v; -} -static grn_cell * -nf_rem(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register int64_t v; - register grn_cell *x; - x = args; - if (grn_obj2int(ctx, CAR(x))) { - QLERR("can't convert into integer"); - } - v = IVALUE(CAR(x)); - while (CDR(x) != NIL) { - x = CDR(x); - if (grn_obj2int(ctx, CAR(x))) { - QLERR("can't convert into integer"); - } - if (IVALUE(CAR(x)) != 0) - v %= IVALUE(CAR(x)); - else { - QLERR("Divided by zero"); - } - } - return mk_number(ctx, v); -} -static grn_cell * -nf_car(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (PAIRP(CAR(args))) { - return CAAR(args); - } else { - QLERR("Unable to car for non-cons cell"); - } -} -static grn_cell * -nf_cdr(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (PAIRP(CAR(args))) { - return CDAR(args); - } else { - QLERR("Unable to cdr for non-cons cell"); - } -} -static grn_cell * -nf_cons(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - CDR(args) = CADR(args); - return args; -} -static grn_cell * -nf_not(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(isfalse(CAR(args))); -} -static grn_cell * -nf_bool(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(CAR(args) == F || CAR(args) == T); -} -static grn_cell * -nf_null(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(CAR(args) == NIL); -} -static grn_cell * -nf_zerop(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *x = CAR(args); - switch (x->header.type) { - case GRN_CELL_INT : - s_retbool(IVALUE(x) == 0); - break; - case GRN_CELL_FLOAT : - s_retbool(!(islessgreater(FVALUE(x), 0.0))); - break; - default : - QLERR("can't convert into numeric value"); - } -} -static grn_cell * -nf_posp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *x = CAR(args); - switch (x->header.type) { - case GRN_CELL_INT : - s_retbool(IVALUE(x) > 0); - break; - case GRN_CELL_FLOAT : - s_retbool(!(isgreater(FVALUE(x), 0.0))); - break; - default : - QLERR("can't convert into numeric value"); - } -} -static grn_cell * -nf_negp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *x = CAR(args); - switch (x->header.type) { - case GRN_CELL_INT : - s_retbool(IVALUE(x) < 0); - break; - case GRN_CELL_FLOAT : - s_retbool(!(isless(FVALUE(x), 0.0))); - break; - default : - QLERR("can't convert into numeric value"); - } -} -static grn_cell * -nf_neq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 1; - register grn_cell *x, *y; - POP(x, args); - if (!PAIRP(args)) { QLERR("Few arguments"); } - do { - POP(y, args); - switch (x->header.type) { - case GRN_CELL_INT : - switch (y->header.type) { - case GRN_CELL_INT : - r = (IVALUE(x) == IVALUE(y)); - break; - case GRN_CELL_FLOAT : - r = (IVALUE(x) <= FVALUE(y) && IVALUE(x) >= FVALUE(y)); - break; - default : - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); } - r = (IVALUE(x) == IVALUE(y)); - } - break; - case GRN_CELL_FLOAT : - switch (y->header.type) { - case GRN_CELL_INT : - r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y)); - break; - case GRN_CELL_FLOAT : - r = (FVALUE(x) <= FVALUE(y) && FVALUE(x) >= FVALUE(y)); - break; - default : - if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); } - r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y)); - } - break; - case GRN_CELL_STR : - if (y->header.type == GRN_CELL_STR) { - int r_; - uint32_t la = x->u.b.size, lb = y->u.b.size; - if (la > lb) { - if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) { - r_ = 1; - } - } else { - if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) { - r_ = la == lb ? 0 : -1; - } - } - r = (r_ == 0); - } else { - QLERR("can't compare"); - } - break; - case GRN_CELL_TIME : - if (y->header.type == GRN_CELL_TIME) { - if (x->u.tv.tv_sec != y->u.tv.tv_sec) { - r = (x->u.tv.tv_sec == y->u.tv.tv_sec); - } else { - r = (x->u.tv.tv_nsec == y->u.tv.tv_nsec); - } - } else { - QLERR("can't compare"); - } - break; - case GRN_CELL_OBJECT : - r = (y->header.type == GRN_CELL_OBJECT && - x->u.o.id == y->u.o.id && x->header.domain == y->header.domain); - break; - default : - r = (memcmp(&x->u.tv, &y->u.tv, sizeof(grn_timeval)) == 0); - break; - } - x = y; - } while (PAIRP(args) && r); - return r ? T : F; -} -static grn_cell * -nf_less(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 1; - register grn_cell *x, *y; - POP(x, args); - if (!PAIRP(args)) { QLERR("Few arguments"); } - do { - POP(y, args); - do_compare(x, y, r, <); - x = y; - } while (PAIRP(args) && r); - return r ? T : F; -} -static grn_cell * -nf_gre(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 1; - register grn_cell *x, *y; - POP(x, args); - if (!PAIRP(args)) { QLERR("Few arguments"); } - do { - POP(y, args); - do_compare(x, y, r, >); - x = y; - } while (PAIRP(args) && r); - return r ? T : F; -} -static grn_cell * -nf_leq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 1; - register grn_cell *x, *y; - POP(x, args); - if (!PAIRP(args)) { QLERR("Few arguments"); } - do { - POP(y, args); - do_compare(x, y, r, <=); - x = y; - } while (PAIRP(args) && r); - return r ? T : F; -} -static grn_cell * -nf_geq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 1; - register grn_cell *x, *y; - POP(x, args); - if (!PAIRP(args)) { QLERR("Few arguments"); } - do { - POP(y, args); - do_compare(x, y, r, >=); - x = y; - } while (PAIRP(args) && r); - return r ? T : F; -} -static grn_cell * -nf_symbol(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(SYMBOLP(CAR(args))); -} -static grn_cell * -nf_number(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(NUMBERP(CAR(args))); -} -static grn_cell * -nf_string(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(BULKP(CAR(args))); -} -static grn_cell * -nf_proc(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - /*-- - * continuation should be procedure by the example - * (call-with-current-continuation procedure?) ==> #t - * in R^3 report sec. 6.9 - */ - s_retbool(PROCEDUREP(CAR(args))); -} -static grn_cell * -nf_pair(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(PAIRP(CAR(args))); -} -static grn_cell * -nf_eq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(CAR(args) == CADR(args)); -} -static grn_cell * -nf_eqv(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(eqv(CAR(args), CADR(args))); -} -static grn_cell * -nf_logtest(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(logtest(CAR(args), CADR(args))); -} -static grn_cell * -nf_write(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - args = CAR(args); - grn_obj_inspect(ctx, args, ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC); - return T; -} -static grn_cell * -nf_display(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - args = CAR(args); - grn_obj_inspect(ctx, args, ctx->impl->outbuf, 0); - return T; -} -static grn_cell * -nf_newline(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n'); - return T; -} -static grn_cell * -nf_reverse(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - return reverse(ctx, CAR(args)); -} -static grn_cell * -nf_append(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - return append(ctx, CAR(args), CADR(args)); -} -static grn_cell * -nf_gc(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_ctx_mgc(ctx); - return T; -} -static grn_cell * -nf_gcverb(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int was = ctx->impl->gc_verbose; - ctx->impl->gc_verbose = (CAR(args) != F); - s_retbool(was); -} -static grn_cell * -nf_nativep(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(NATIVE_FUNCP(CAR(args))); -} -static grn_cell * -nf_length(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register long v; - register grn_cell *x; - for (x = CAR(args), v = 0; PAIRP(x); x = CDR(x)) { ++v; } - return mk_number(ctx, v); -} -static grn_cell * -nf_assq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - register grn_cell *x, *y; - x = CAR(args); - for (y = CADR(args); PAIRP(y); y = CDR(y)) { - if (!PAIRP(CAR(y))) { - QLERR("Unable to handle non pair element"); - } - if (x == CAAR(y)) - break; - } - if (PAIRP(y)) { - return CAR(y); - } else { - return F; - } -} -static grn_cell * -nf_get_closure(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - args = CAR(args); - if (args == NIL) { - return F; - } else if (CLOSUREP(args)) { - return CONS(LAMBDA, CLOSURE_CODE(ctx->impl->value)); - } else { - return F; - } -} -static grn_cell * -nf_closurep(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - /* - * Note, macro object is also a closure. - * Therefore, (closure? <#MACRO>) ==> #t - */ - if (CAR(args) == NIL) { - return F; - } - s_retbool(CLOSUREP(CAR(args))); -} -static grn_cell * -nf_macrop(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (CAR(args) == NIL) { - return F; - } - s_retbool(MACROP(CAR(args))); -} -static grn_cell * -nf_voidp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - s_retbool(CAR(args)->header.type == GRN_VOID); -} -static grn_cell * -nf_list(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (PAIRP(args)) { - return args; - } else { - QLERR("Unable to handle non-cons argument"); - } -} -static grn_cell * -nf_batchmode(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - if (CAR(args) == F) { - ctx->impl->batchmode = 0; - return F; - } else { - ctx->impl->batchmode = 1; - return T; - } -} -static grn_cell * -nf_loglevel(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - static grn_logger_info info; - grn_cell *x = CAR(args); - if (grn_obj2int(ctx, x)) { QLERR("can't convert into integer"); } - info.max_level = IVALUE(x); - info.flags = GRN_LOG_TIME|GRN_LOG_MESSAGE; - info.func = NULL; - info.func_arg = NULL; - return (grn_logger_info_set(ctx, &info)) ? F : T; -} -static grn_cell * -nf_log_put(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *x, *y; - grn_log_level level = GRN_LOG_DEFAULT_LEVEL; - POP(x, args); - POP(y, args); - if (y->header.type == GRN_CELL_INT) { level = IVALUE(y); } - if (x->header.type == GRN_CELL_STR) { - char *buf = GRN_MALLOC(x->u.b.size + 1); - memcpy(buf, x->u.b.value, x->u.b.size); - buf[x->u.b.size] = '\0'; - GRN_LOG(ctx, level, "%s", buf); - GRN_FREE(buf); - return T; - } else { - return F; - } -} -static grn_cell * -nf_now(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *x; - grn_timeval tv; - if (grn_timeval_now(ctx, &tv)) { QLERR("sysdate failed"); } - GRN_CELL_NEW(ctx, x); - SETTIME(x, &tv); - return x; -} -static grn_cell * -nf_timestr(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_timeval tv; - char buf[GRN_TIMEVAL_STR_SIZE]; - grn_cell *x = CAR(args); - switch (x->header.type) { - case GRN_CELL_STR : - if (grn_obj2int(ctx, x)) { QLERR("can't convert into integer"); } - /* fallthru */ - case GRN_CELL_INT : - tv.tv_sec = IVALUE(x); - tv.tv_nsec = 0; - break; - case GRN_CELL_FLOAT : - tv.tv_sec = (int32_t) FVALUE(x); - tv.tv_nsec = (int32_t) ((FVALUE(x) - tv.tv_sec) * GRN_TIME_NSEC_PER_SEC); - break; - case GRN_CELL_TIME : - memcpy(&tv, &x->u.tv, sizeof(grn_timeval)); - break; - default : - QLERR("can't convert into time"); - } - if (grn_timeval2str(ctx, &tv, buf)) { QLERR("timeval2str failed"); } - return grn_ql_mk_string(ctx, buf, strlen(buf)); -} -static grn_cell * -nf_tonumber(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *x, *v; - if (!PAIRP(args)) { QLERR("list required"); } - x = CAR(args); - switch (x->header.type) { - case GRN_CELL_STR : - if ((v = str2num(ctx, STRVALUE(x), x->u.b.size)) == NIL) { v = mk_number(ctx, 0); } - break; - case GRN_CELL_INT : - case GRN_CELL_FLOAT : - v = x; - break; - case GRN_CELL_TIME : - { - double dv= x->u.tv.tv_sec; - dv += x->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F; - GRN_CELL_NEW(ctx, v); - SETFLOAT(v, dv); - } - break; - default : - v = mk_number(ctx, 0); - break; - } - return v; -} -static grn_cell * -nf_totime(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_timeval tv; - grn_cell *x, *v; - if (!PAIRP(args)) { QLERR("list required"); } - x = CAR(args); - switch (x->header.type) { - case GRN_CELL_STR : - { - /* - if (PAIRP(CDR(args)) && BULKP(CADR(args))) { fmt = STRVALUE(CADR(args)); } - */ - if (grn_str2timeval(STRVALUE(x), x->u.b.size, &tv)) { - QLERR("cast error"); - } - GRN_CELL_NEW(ctx, v); - SETTIME(v, &tv); - } - break; - case GRN_CELL_INT : - tv.tv_sec = (int32_t) IVALUE(x); - tv.tv_nsec = 0; - GRN_CELL_NEW(ctx, v); - SETTIME(v, &tv); - break; - case GRN_CELL_FLOAT : - tv.tv_sec = (int32_t) FVALUE(x); - tv.tv_nsec = (int32_t) ((FVALUE(x) - tv.tv_sec) * GRN_TIME_NSEC_PER_SEC); - GRN_CELL_NEW(ctx, v); - SETTIME(v, &tv); - break; - case GRN_CELL_TIME : - v = x; - break; - default : - QLERR("can't convert into number"); - } - return v; -} -static grn_cell * -nf_substrb(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *str, *s, *e; - int64_t is, ie; - if (!PAIRP(args)) { QLERR("list required"); } - POP(str, args); - if (!BULKP(str)) { QLERR("string required"); } - POP(s, args); - if (!INTP(s)) { QLERR("integer required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - is = IVALUE(s); - ie = IVALUE(e) + 1; - if (ie <= 0) { - ie = str->u.b.size + ie; - if (ie < 0) { ie = 0; } - } else if (ie > str->u.b.size) { - ie = str->u.b.size; - } - if (is < 0) { - is = str->u.b.size + is + 1; - if (is < 0) { is = 0; } - } else if (is > str->u.b.size) { - is = str->u.b.size; - } - if (is < ie) { - return grn_ql_mk_string(ctx, STRVALUE(str) + is, ie - is); - } else { - grn_cell *o; - GRN_CELL_NEW(ctx, o); - o->header.impl_flags = 0; - o->header.type = GRN_CELL_STR; - o->u.b.size = 0; - o->u.b.value = NULL; - return o; - } -} -static grn_cell * -nf_tob32h(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *x, *v; - if (!PAIRP(args)) { QLERR("list required"); } - x = CAR(args); - switch (x->header.type) { - case GRN_CELL_INT : - { - grn_obj buf; - GRN_TEXT_INIT(&buf, 0); - grn_bulk_resize(ctx, &buf, 13); - if (grn_text_lltob32h(ctx, &buf, IVALUE(x))) { - grn_bulk_fin(ctx, &buf); - QLERR("lltob32h failed"); - } - GRN_STR2OBJ(ctx, &buf, v); - } - break; - case GRN_CELL_FLOAT : - { - grn_obj buf; - GRN_TEXT_INIT(&buf, 0); - grn_bulk_resize(ctx, &buf, 13); - if (grn_text_lltob32h(ctx, &buf, (int64_t)FVALUE(x))) { - grn_bulk_fin(ctx, &buf); - QLERR("lltob32h failed"); - } - GRN_STR2OBJ(ctx, &buf, v); - } - break; - default : - QLERR("can't convert into int"); - } - return v; -} -static grn_cell * -nf_intern(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *x, *v; - if (!PAIRP(args)) { QLERR("list required"); } - x = CAR(args); - if SYMBOLP(x) { return x; } - switch (x->header.type) { - case GRN_CELL_STR : - v = grn_ql_mk_symbol2(ctx, STRVALUE(x), STRSIZE(x), 0); - break; - default : - QLERR("can't convert into string"); - } - return v; -} -static grn_cell * -nf_containp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - int r = 0; - grn_id id; - grn_cell *e, *car; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - switch (e->header.type) { - case GRN_UVECTOR : - { - grn_obj *u = e->u.p.value, *range = grn_ctx_at(ctx, u->header.domain); - grn_id *v, *ve = (grn_id *)GRN_BULK_CURR(u); - POP(e, args); - switch (e->header.type) { - case GRN_CELL_LIST : - r = 1; - while (r && PAIRP(e)) { - POP(car, e); - switch (car->header.type) { - case GRN_CELL_OBJECT : - if (car->header.domain == u->header.domain && (id = car->u.o.id)) { - for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) { - if (v == ve) { r = 0; break; } - if (*v == id) { break; } - } - } else { - r = 0; - } - break; - case GRN_CELL_STR : - id = grn_table_get(ctx, range, STRVALUE(car), STRSIZE(car)); - if (id) { - for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) { - if (v == ve) { r = 0; break; } - if (*v == id) { break; } - } - } else { - r = 0; - } - break; - default : - r = 0; - break; - } - } - break; - case GRN_CELL_STR : - id = grn_table_get(ctx, range, STRVALUE(e), STRSIZE(e)); - if (id) { - for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) { - if (v == ve) { r = 0; break; } - if (*v == id) { r = 1; break; } - } - } else { - r = 0; - } - break; - case GRN_CELL_OBJECT : - if (e->header.domain == u->header.domain && (id = e->u.o.id)) { - for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) { - if (v == ve) { r = 0; break; } - if (*v == id) { r = 1; break; } - } - } else { - r = 0; - } - break; - default : - r = 0; - break; - } - } - break; - case GRN_CELL_OBJECT : - { - grn_id domain = e->header.domain; - id = e->u.o.id; - POP(e, args); - if (e->header.type == GRN_CELL_LIST) { e = CAR(e); } - switch (e->header.type) { - case GRN_CELL_STR : - { - grn_obj *range = grn_ctx_at(ctx, domain); - if (grn_table_get(ctx, range, STRVALUE(e), STRSIZE(e)) == id) { r = 1; } - } - break; - case GRN_CELL_OBJECT : - if (e->header.domain == domain && e->u.o.id == id) { r = 1; } - break; - default : - r = 0; - break; - } - } - break; - default : - QLERR("uvector or object required"); - break; - } - return r ? T : F; -} - -#define GEO_RESOLUTION 3600000 -#define GEO_RADIOUS 6357303 -#define GEO_BES_C1 6334834 -#define GEO_BES_C2 6377397 -#define GEO_BES_C3 0.006674 -#define GEO_GRS_C1 6335439 -#define GEO_GRS_C2 6378137 -#define GEO_GRS_C3 0.006694 -#define GEO_INT2RAD(x) ((M_PI * x) / (GEO_RESOLUTION * 180)) - -static grn_cell * -nf_geo_distance1(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *e; - double lng1, lat1, lng2, lat2, x, y, d; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng2 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat2 = GEO_INT2RAD(IVALUE(e)); - x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5); - y = (lat2 - lat1); - d = sqrt((x * x) + (y * y)) * GEO_RADIOUS; - GRN_CELL_NEW(ctx, e); - SETFLOAT(e, d); - return e; -} -static grn_cell * -nf_geo_distance2(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *e; - double lng1, lat1, lng2, lat2, x, y, d; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng2 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat2 = GEO_INT2RAD(IVALUE(e)); - x = sin(fabs(lng2 - lng1) * 0.5); - y = sin(fabs(lat2 - lat1) * 0.5); - d = asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GEO_RADIOUS; - GRN_CELL_NEW(ctx, e); - SETFLOAT(e, d); - return e; -} -static grn_cell * -nf_geo_distance3(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *e; - double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng2 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat2 = GEO_INT2RAD(IVALUE(e)); - p = (lat1 + lat2) * 0.5; - q = (1 - GEO_BES_C3 * sin(p) * sin(p)); - m = GEO_BES_C1 / sqrt(q * q * q); - n = GEO_BES_C2 / sqrt(q); - x = n * cos(p) * fabs(lng1 - lng2); - y = m * fabs(lat1 - lat2); - d = sqrt((x * x) + (y * y)); - GRN_CELL_NEW(ctx, e); - SETFLOAT(e, d); - return e; -} -static grn_cell * -nf_geo_distance4(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *e; - double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat1 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lng2 = GEO_INT2RAD(IVALUE(e)); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - lat2 = GEO_INT2RAD(IVALUE(e)); - p = (lat1 + lat2) * 0.5; - q = (1 - GEO_GRS_C3 * sin(p) * sin(p)); - m = GEO_GRS_C1 / sqrt(q * q * q); - n = GEO_GRS_C2 / sqrt(q); - x = n * cos(p) * fabs(lng1 - lng2); - y = m * fabs(lat1 - lat2); - d = sqrt((x * x) + (y * y)); - GRN_CELL_NEW(ctx, e); - SETFLOAT(e, d); - return e; -} -static grn_cell * -nf_geo_withinp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co) -{ - grn_cell *e; - int64_t ln0, la0, ln1, la1, ln2, la2, ln3, la3; - double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d; - if (!PAIRP(args)) { QLERR("list required"); } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - ln0 = IVALUE(e); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - la0 = IVALUE(e); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - ln1 = IVALUE(e); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - la1 = IVALUE(e); - if (args == NIL) { return T; } - POP(e, args); - if (args == NIL) { - lng0 = GEO_INT2RAD(ln0); - lat0 = GEO_INT2RAD(la0); - lng1 = GEO_INT2RAD(ln1); - lat1 = GEO_INT2RAD(la1); - x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5); - y = (lat1 - lat0); - d = sqrt((x * x) + (y * y)) * GEO_RADIOUS; - switch (e->header.type) { - case GRN_CELL_INT : return d <= IVALUE(e) ? T : F; - case GRN_CELL_FLOAT : return d <= FVALUE(e) ? T : F; - default : QLERR("integer or float value required"); - } - } - if (!INTP(e)) { QLERR("integer required"); } - ln2 = IVALUE(e); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - la2 = IVALUE(e); - if (args == NIL) { - lng0 = GEO_INT2RAD(ln0); - lat0 = GEO_INT2RAD(la0); - lng1 = GEO_INT2RAD(ln1); - lat1 = GEO_INT2RAD(la1); - lng2 = GEO_INT2RAD(ln2); - lat2 = GEO_INT2RAD(la2); - x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5); - y = (lat1 - lat0); - d = (x * x) + (y * y); - x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5); - y = (lat2 - lat1); - return d <= (x * x) + (y * y) ? T : F; - } - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - ln3 = IVALUE(e); - POP(e, args); - if (!INTP(e)) { QLERR("integer required"); } - la3 = IVALUE(e); - return ((ln2 <= ln0) && (ln0 <= ln3) && (la2 <= la0) && (la0 <= la3)) ? T : F; -} - -/* ========== Initialization of internal keywords ========== */ - -inline static void -mk_syntax(grn_ctx *ctx, uint8_t op, const char *name) -{ - grn_cell *x; - if ((x = INTERN(name)) != F) { - x->header.type = GRN_CELL_SYNTAX; - SYNTAXNUM(x) = op; - } -} - -inline static void -mk_proc(grn_ctx *ctx, uint8_t op, const char *name) -{ - grn_cell *x; - if ((x = INTERN(name)) != F) { - x->header.type = GRN_CELL_PROC; - IVALUE(x) = (int64_t) op; - } -} - -void -grn_ql_init_const(void) -{ - static grn_cell _NIL, _T, _F; - /* init NIL */ - NIL = &_NIL; - NIL->header.type = GRN_VOID; - CAR(NIL) = CDR(NIL) = NIL; - /* init T */ - T = &_T; - T->header.type = GRN_VOID; - CAR(T) = CDR(T) = T; - /* init F */ - F = &_F; - F->header.type = GRN_VOID; - CAR(F) = CDR(F) = F; -} - -inline static void -init_vars_global(grn_ctx *ctx) -{ - grn_cell *x; - /* init global_env */ - ctx->impl->global_env = CONS(NIL, NIL); - /* init else */ - if ((x = INTERN("else")) != F) { - CAR(ctx->impl->global_env) = CONS(CONS(x, T), CAR(ctx->impl->global_env)); - } -} - -inline static void -init_syntax(grn_ctx *ctx) -{ - /* init syntax */ - mk_syntax(ctx, OP_LAMBDA, "lambda"); - mk_syntax(ctx, OP_QUOTE, "quote"); - mk_syntax(ctx, OP_DEF0, "define"); - mk_syntax(ctx, OP_IF0, "if"); - mk_syntax(ctx, OP_BEGIN, "begin"); - mk_syntax(ctx, OP_SET0, "set!"); - mk_syntax(ctx, OP_LET0, "let"); - mk_syntax(ctx, OP_LET0AST, "let*"); - mk_syntax(ctx, OP_LET0REC, "letrec"); - mk_syntax(ctx, OP_COND0, "cond"); - mk_syntax(ctx, OP_DELAY, "delay"); - mk_syntax(ctx, OP_AND0, "and"); - mk_syntax(ctx, OP_OR0, "or"); - mk_syntax(ctx, OP_C0STREAM, "cons-stream"); - mk_syntax(ctx, OP_0MACRO, "define-macro"); - mk_syntax(ctx, OP_CASE0, "case"); - mk_syntax(ctx, OP_QQUOTE0, "quasiquote"); -} - -inline static void -init_procs(grn_ctx *ctx) -{ - /* init procedure */ - mk_proc(ctx, OP_PEVAL, "eval"); - mk_proc(ctx, OP_PAPPLY, "apply"); - mk_proc(ctx, OP_CONTINUATION, "call-with-current-continuation"); - mk_proc(ctx, OP_FORCE, "force"); - mk_proc(ctx, OP_SETCAR, "set-car!"); - mk_proc(ctx, OP_SETCDR, "set-cdr!"); - mk_proc(ctx, OP_READ, "read"); - mk_proc(ctx, OP_LOAD, "load"); - mk_proc(ctx, OP_ERR1, "error"); - mk_proc(ctx, OP_PUT, "put"); - mk_proc(ctx, OP_GET, "get"); - mk_proc(ctx, OP_QUIT, "quit"); - mk_proc(ctx, OP_SDOWN, "shutdown"); - grn_ql_def_native_func(ctx, "+", nf_add); - grn_ql_def_native_func(ctx, "-", nf_sub); - grn_ql_def_native_func(ctx, "*", nf_mul); - grn_ql_def_native_func(ctx, "/", nf_div); - grn_ql_def_native_func(ctx, "remainder", nf_rem); - grn_ql_def_native_func(ctx, "car", nf_car); - grn_ql_def_native_func(ctx, "cdr", nf_cdr); - grn_ql_def_native_func(ctx, "cons", nf_cons); - grn_ql_def_native_func(ctx, "not", nf_not); - grn_ql_def_native_func(ctx, "boolean?", nf_bool); - grn_ql_def_native_func(ctx, "symbol?", nf_symbol); - grn_ql_def_native_func(ctx, "number?", nf_number); - grn_ql_def_native_func(ctx, "string?", nf_string); - grn_ql_def_native_func(ctx, "procedure?", nf_proc); - grn_ql_def_native_func(ctx, "pair?", nf_pair); - grn_ql_def_native_func(ctx, "eqv?", nf_eqv); - grn_ql_def_native_func(ctx, "logtest", nf_logtest); - grn_ql_def_native_func(ctx, "eq?", nf_eq); - grn_ql_def_native_func(ctx, "null?", nf_null); - grn_ql_def_native_func(ctx, "zero?", nf_zerop); - grn_ql_def_native_func(ctx, "positive?", nf_posp); - grn_ql_def_native_func(ctx, "negative?", nf_negp); - grn_ql_def_native_func(ctx, "=", nf_neq); - grn_ql_def_native_func(ctx, "<", nf_less); - grn_ql_def_native_func(ctx, ">", nf_gre); - grn_ql_def_native_func(ctx, "<=", nf_leq); - grn_ql_def_native_func(ctx, ">=", nf_geq); - grn_ql_def_native_func(ctx, "write", nf_write); - grn_ql_def_native_func(ctx, "display", nf_display); - grn_ql_def_native_func(ctx, "newline", nf_newline); - grn_ql_def_native_func(ctx, "reverse", nf_reverse); - grn_ql_def_native_func(ctx, "append", nf_append); - grn_ql_def_native_func(ctx, "gc", nf_gc); - grn_ql_def_native_func(ctx, "gc-verbose", nf_gcverb); - grn_ql_def_native_func(ctx, "native?", nf_nativep); - grn_ql_def_native_func(ctx, "length", nf_length); /* a.k */ - grn_ql_def_native_func(ctx, "assq", nf_assq); /* a.k */ - grn_ql_def_native_func(ctx, "get-closure-code", nf_get_closure); /* a.k */ - grn_ql_def_native_func(ctx, "closure?", nf_closurep); /* a.k */ - grn_ql_def_native_func(ctx, "macro?", nf_macrop); /* a.k */ - grn_ql_def_native_func(ctx, "void?", nf_voidp); - grn_ql_def_native_func(ctx, "list", nf_list); - grn_ql_def_native_func(ctx, "batchmode", nf_batchmode); - grn_ql_def_native_func(ctx, "loglevel", nf_loglevel); - grn_ql_def_native_func(ctx, "log-put", nf_log_put); - grn_ql_def_native_func(ctx, "now", nf_now); - grn_ql_def_native_func(ctx, "timestr", nf_timestr); - grn_ql_def_native_func(ctx, "x->time", nf_totime); - grn_ql_def_native_func(ctx, "x->number", nf_tonumber); - grn_ql_def_native_func(ctx, "substrb", nf_substrb); - grn_ql_def_native_func(ctx, "x->b32h", nf_tob32h); - grn_ql_def_native_func(ctx, "intern", nf_intern); - grn_ql_def_native_func(ctx, "contain?", nf_containp); - grn_ql_def_native_func(ctx, "geo-distance1", nf_geo_distance1); - grn_ql_def_native_func(ctx, "geo-distance2", nf_geo_distance2); - grn_ql_def_native_func(ctx, "geo-distance3", nf_geo_distance3); - grn_ql_def_native_func(ctx, "geo-distance4", nf_geo_distance4); - grn_ql_def_native_func(ctx, "geo-within?", nf_geo_withinp); -} - -/* initialize several globals */ -void -grn_ql_init_globals(grn_ctx *ctx) -{ - init_vars_global(ctx); - init_syntax(ctx); - init_procs(ctx); - ctx->impl->output = grn_ctx_concat_func; - /* initialization of global pointers to special symbols */ -} Modified: lib/store.c (+1 -1) =================================================================== --- lib/store.c 2012-02-03 11:43:41 +0900 (983f354) +++ lib/store.c 2012-01-17 12:10:35 +0900 (80c77b8) @@ -17,7 +17,7 @@ #include "groonga_in.h" #include "str.h" #include "store.h" -#include "ql.h" +#include "ctx_impl.h" #include "output.h" #include <string.h> Modified: lib/token.c (+1 -1) =================================================================== --- lib/token.c 2012-02-03 11:43:41 +0900 (f8cc681) +++ lib/token.c 2012-01-17 12:10:35 +0900 (f387b44) @@ -18,7 +18,7 @@ #include "groonga_in.h" #include <string.h> #include <ctype.h> -#include "ql.h" +#include "ctx_impl.h" #include "token.h" #include "pat.h" #include "dat.h" Modified: src/grnslap.c (+1 -1) =================================================================== --- src/grnslap.c 2012-02-03 11:43:41 +0900 (73e09f5) +++ src/grnslap.c 2012-01-17 12:10:35 +0900 (a2d3ec6) @@ -17,7 +17,7 @@ */ #include "lib/com.h" -#include "lib/ql.h" +#include "lib/ctx_impl.h" #include <string.h> #include <stdio.h> #ifdef HAVE_SYS_WAIT_H Modified: src/groonga.c (+1 -1) =================================================================== --- src/groonga.c 2012-02-03 11:43:41 +0900 (2da335e) +++ src/groonga.c 2012-01-17 12:10:35 +0900 (bdcc6c9) @@ -22,7 +22,7 @@ #include "lib/groonga_in.h" #include "lib/com.h" -#include "lib/ql.h" +#include "lib/ctx_impl.h" #include "lib/proc.h" #include "lib/db.h" #include "lib/util.h" Modified: test/unit/core/Makefile.am (+0 -2) =================================================================== --- test/unit/core/Makefile.am 2012-02-03 11:43:41 +0900 (473bc7b) +++ test/unit/core/Makefile.am 2012-01-17 12:10:35 +0900 (3e5c9d3) @@ -14,7 +14,6 @@ noinst_LTLIBRARIES = \ test-performance.la \ test-stress.la \ test-public-context.la \ - test-query.la \ test-table.la \ test-table-patricia-trie-cursor.la \ test-table-sort-geo.la \ @@ -102,7 +101,6 @@ test_patricia_trie_search_la_SOURCES = test-patricia-trie-search.c test_performance_la_SOURCES = test-performance.c test_stress_la_SOURCES = test-stress.c test_public_context_la_SOURCES = test-public-context.c -test_query_la_SOURCES = test-query.c test_table_la_SOURCES = test-table.c test_table_patricia_trie_cursor_la_SOURCES = test-table-patricia-trie-cursor.c test_table_sort_geo_la_SOURCES = test-table-sort-geo.c Modified: test/unit/core/test-inverted-index.c (+42 -10) =================================================================== --- test/unit/core/test-inverted-index.c 2012-02-03 11:43:41 +0900 (3ad45c4) +++ test/unit/core/test-inverted-index.c 2012-01-17 12:10:35 +0900 (2d10c6a) @@ -723,13 +723,28 @@ test_mroonga_index(void) /* boolean search */ { grn_id id, docid; + grn_obj *match_columns, *match_columns_variable; + grn_obj *expression, *expression_variable; grn_obj *res; - grn_query *query; grn_table_cursor *tc; + const char *match_columns_expression = "c1"; const char *qstr = "+22 -55"; + + GRN_EXPR_CREATE_FOR_QUERY(context, t1, + match_columns, match_columns_variable); + grn_expr_parse(context, match_columns, + match_columns_expression, + strlen(match_columns_expression), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + GRN_EXPR_CREATE_FOR_QUERY(context, t1, expression, expression_variable); res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0); - query = grn_query_open(context, qstr, strlen(qstr), GRN_OP_OR, 32); - grn_obj_search(context, ft, (grn_obj*) query, res, GRN_OP_OR, NULL); + grn_test_assert(grn_expr_parse(context, expression, + qstr, strlen(qstr), + match_columns, + GRN_OP_MATCH, GRN_OP_OR, + GRN_EXPR_SYNTAX_QUERY)); + grn_table_select(context, t1, expression, res, GRN_OP_OR); cut_assert_equal_int(1, grn_table_size(context, res)); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0); while ((id = grn_table_cursor_next(context, tc))) { @@ -740,7 +755,8 @@ test_mroonga_index(void) cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); } - grn_query_close(context, query); + grn_obj_close(context, expression); + grn_obj_close(context, match_columns); grn_table_cursor_close(context ,tc); grn_obj_close(context, res); } @@ -862,16 +878,31 @@ test_mroonga_index_score(void) { grn_id id, docid; grn_obj *res; - grn_query *query; + grn_obj *match_columns, *match_columns_variable; + grn_obj *expression, *expression_variable; grn_table_cursor *tc; grn_obj score, *score_column; + const char *match_columns_expression = "c1 * 5"; const char *qstr = "+22 -55"; + + GRN_EXPR_CREATE_FOR_QUERY(context, t1, + match_columns, match_columns_variable); + grn_expr_parse(context, match_columns, + match_columns_expression, + strlen(match_columns_expression), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + GRN_EXPR_CREATE_FOR_QUERY(context, t1, expression, expression_variable); res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, t1, 0); - GRN_UINT32_INIT(&score, 0); - query = grn_query_open(context, qstr, strlen(qstr), GRN_OP_OR, 32); - grn_obj_search(context, ft, (grn_obj*) query, res, GRN_OP_OR, NULL); + grn_test_assert(grn_expr_parse(context, expression, + qstr, strlen(qstr), + match_columns, + GRN_OP_MATCH, GRN_OP_OR, + GRN_EXPR_SYNTAX_QUERY)); + grn_table_select(context, t1, expression, res, GRN_OP_OR); cut_assert_equal_int(1, grn_table_size(context, res)); + GRN_UINT32_INIT(&score, 0); score_column = grn_obj_column(context, res, "_score", 6); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0); while ((id = grn_table_cursor_next(context, tc))) { @@ -879,12 +910,13 @@ test_mroonga_index_score(void) grn_table_get_key(context, res, id, &docid, sizeof(grn_id)); cut_assert_equal_int(3, docid); cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff)); - cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff)); + cut_assert_equal_int(8, GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); grn_obj_get_value(context, score_column, id, &score); cut_assert_equal_uint(5, GRN_UINT32_VALUE(&score)); } - grn_query_close(context, query); + grn_obj_close(context, expression); + grn_obj_close(context, match_columns); grn_table_cursor_close(context ,tc); grn_obj_close(context, score_column); grn_obj_close(context, res); Deleted: test/unit/core/test-query.c (+0 -64) 100644 =================================================================== --- test/unit/core/test-query.c 2012-02-03 11:43:41 +0900 (bd61eb9) +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c-basic-offset: 2; coding: utf-8 -*- */ -/* - Copyright (C) 2008-2009 Kouhei Sutou <kou****@cozmi*****> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include <groonga.h> - -#include <gcutter.h> - -#include "../lib/grn-assertions.h" - -void attributes_open_broken_utf8(void); -void test_open_broken_utf8(void); - -static grn_ctx *context; -static grn_query *query; - -void -cut_setup(void) -{ - context = g_new0(grn_ctx, 1); - grn_ctx_init(context, GRN_CTX_USE_QL); - query = NULL; -} - -void -cut_teardown(void) -{ - if (context) { - if (query) - grn_obj_close(context, (grn_obj *)query); - grn_ctx_fin(context); - g_free(context); - } -} - -void -attributes_open_broken_utf8(void) -{ - cut_set_attributes("ML", "senna-dev:1070", - NULL); -} - -void -test_open_broken_utf8(void) -{ - gchar utf8[] = "\"あ\""; - GRN_CTX_SET_ENCODING(context, GRN_ENC_UTF8); - query = grn_query_open(context, utf8, 2, GRN_OP_OR, 10); - cut_assert_not_null(query); -}