Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mrb.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /*
3  Copyright(C) 2013 Brazil
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License version 2.1 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "mrb.h"
20 #include "ctx_impl.h"
21 
22 #ifdef GRN_WITH_MRUBY
23 # include <mruby/proc.h>
24 # include <mruby/compile.h>
25 # include <mruby/string.h>
26 #endif
27 
28 #define BUFFER_SIZE 2048
29 
30 #ifdef GRN_WITH_MRUBY
31 #ifdef WIN32
32 static char *win32_ruby_scripts_dir = NULL;
33 static char win32_ruby_scripts_dir_buffer[PATH_MAX];
34 static const char *
35 grn_mrb_get_system_ruby_scripts_dir(void)
36 {
37  if (!win32_ruby_scripts_dir) {
38  const char *base_dir;
39  const char *relative_path = GRN_RELATIVE_RUBY_SCRIPTS_DIR;
40  char *path;
41  size_t base_dir_length;
42 
43  base_dir = grn_win32_base_dir();
44  base_dir_length = strlen(base_dir);
45  strcpy(win32_ruby_scripts_dir_buffer, base_dir);
46  strcat(win32_ruby_scripts_dir_buffer, "/");
47  strcat(win32_ruby_scripts_dir_buffer, relative_path);
48  win32_ruby_scripts_dir = win32_ruby_scripts_dir_buffer;
49  }
50  return win32_ruby_scripts_dir;
51 }
52 
53 #else /* WIN32 */
54 static const char *
55 grn_mrb_get_system_ruby_scripts_dir(void)
56 {
57  return GRN_RUBY_SCRIPTS_DIR;
58 }
59 #endif /* WIN32 */
60 
61 static FILE *
62 grn_mrb_open_script(grn_ctx *ctx, const char *path)
63 {
64  const char *ruby_scripts_dir;
65  char dir_last_char;
66  char expanded_path[PATH_MAX];
67  int path_length, max_path_length;
68  FILE *script_file = NULL;
69 
70  if (path[0] == '/') {
71  expanded_path[0] = '\0';
72  } else {
73  ruby_scripts_dir = getenv("GRN_RUBY_SCRIPTS_DIR");
74  if (!ruby_scripts_dir) {
75  ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir();
76  }
77  strcpy(expanded_path, ruby_scripts_dir);
78 
79  dir_last_char = ruby_scripts_dir[strlen(expanded_path) - 1];
80  if (dir_last_char != '/') {
81  strcat(expanded_path, "/");
82  }
83  }
84 
85  path_length = strlen(path);
86  max_path_length = PATH_MAX - strlen(expanded_path) - 1;
87  if (path_length > max_path_length) {
89  "script path is too long: %d (max: %d) <%s%s>",
90  path_length, max_path_length,
91  expanded_path, path);
92  return NULL;
93  }
94 
95  strcat(expanded_path, path);
96  script_file = fopen(expanded_path, "r");
97  if (!script_file) {
98  char message[BUFFER_SIZE];
99  snprintf(message, BUFFER_SIZE - 1,
100  "fopen: failed to open mruby script file: <%s>", path);
101  SERR(message);
102  return NULL;
103  }
104 
105  return script_file;
106 }
107 
108 mrb_value
109 grn_mrb_load(grn_ctx *ctx, const char *path)
110 {
111  mrb_state *mrb = ctx->impl->mrb.state;
112  int n;
113  FILE *file;
114  mrb_value result;
115  struct mrb_parser_state *parser;
116 
117  if (!mrb) {
118  return mrb_nil_value();
119  }
120 
121  file = grn_mrb_open_script(ctx, path);
122  if (!file) {
123  mrb_value exception;
124  exception = mrb_exc_new(mrb, E_ARGUMENT_ERROR,
125  ctx->errbuf, strlen(ctx->errbuf));
126  mrb->exc = mrb_obj_ptr(exception);
127  return mrb_nil_value();
128  }
129 
130  parser = mrb_parse_file(mrb, file, NULL);
131  fclose(file);
132 
133  n = mrb_generate_code(mrb, parser);
134  result = mrb_run(mrb,
135  mrb_proc_new(mrb, mrb->irep[n]),
136  mrb_top_self(mrb));
137  mrb_parser_free(parser);
138 
139  return result;
140 }
141 
142 mrb_value
143 grn_mrb_eval(grn_ctx *ctx, const char *script, int script_length)
144 {
145  mrb_state *mrb = ctx->impl->mrb.state;
146  int n;
147  mrb_value result;
148  struct mrb_parser_state *parser;
149 
150  if (!mrb) {
151  return mrb_nil_value();
152  }
153 
154  if (script_length < 0) {
155  script_length = strlen(script);
156  }
157  parser = mrb_parse_nstring(mrb, script, script_length, NULL);
158  n = mrb_generate_code(mrb, parser);
159  result = mrb_run(mrb,
160  mrb_proc_new(mrb, mrb->irep[n]),
161  mrb_top_self(mrb));
162  mrb_parser_free(parser);
163 
164  return result;
165 }
166 
167 grn_rc
168 grn_mrb_to_grn(grn_ctx *ctx, mrb_value mrb_object, grn_obj *grn_object)
169 {
170  grn_rc rc = GRN_SUCCESS;
171 
172  switch (mrb_type(mrb_object)) {
173  case MRB_TT_FALSE :
174  if (mrb_nil_p(mrb_object)) {
175  grn_obj_reinit(ctx, grn_object, GRN_DB_VOID, 0);
176  } else {
177  grn_obj_reinit(ctx, grn_object, GRN_DB_BOOL, 0);
178  GRN_BOOL_SET(ctx, grn_object, GRN_FALSE);
179  }
180  break;
181  case MRB_TT_TRUE :
182  grn_obj_reinit(ctx, grn_object, GRN_DB_BOOL, 0);
183  GRN_BOOL_SET(ctx, grn_object, GRN_TRUE);
184  break;
185  case MRB_TT_FIXNUM :
186  grn_obj_reinit(ctx, grn_object, GRN_DB_INT32, 0);
187  GRN_INT32_SET(ctx, grn_object, mrb_fixnum(mrb_object));
188  break;
189  case MRB_TT_STRING :
190  grn_obj_reinit(ctx, grn_object, GRN_DB_TEXT, 0);
191  GRN_TEXT_SET(ctx, grn_object,
192  RSTRING_PTR(mrb_object),
193  RSTRING_LEN(mrb_object));
194  break;
195  default :
197  break;
198  }
199 
200  return rc;
201 }
202 #endif