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);
-}