funky-cli 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/build_config.rb +50 -2
- data/exe/i386-apple-darwin14 +0 -0
- data/exe/i686-pc-linux-gnu +0 -0
- data/exe/i686-w64-mingw32.exe +0 -0
- data/exe/x86_64-apple-darwin14 +0 -0
- data/exe/x86_64-pc-linux-gnu +0 -0
- data/exe/x86_64-w64-mingw32.exe +0 -0
- data/mrbgem.rake +45 -1
- data/mrblib/funky-cli/helper.rb +13 -0
- data/mrblib/funky-cli/mruby.rb +24 -0
- data/mrblib/funky-cli/setup.rb +140 -0
- data/mrblib/funky-cli/version.rb +1 -1
- data/mrblib/funky-cli.rb +13 -2
- data/mrblib/util.rb +10 -0
- data/src/funky_cli_gem.c +316 -0
- data/src/mirb.c +415 -0
- data/src/mruby.c +244 -0
- data/tools/funky-cli/funky-cli.c +7 -0
- metadata +9 -2
data/src/mirb.c
ADDED
@@ -0,0 +1,415 @@
|
|
1
|
+
/*
|
2
|
+
** mirb - Embeddable Interactive Ruby Shell
|
3
|
+
**
|
4
|
+
** This program takes code from the user in
|
5
|
+
** an interactive way and executes it
|
6
|
+
** immediately. It's a REPL...
|
7
|
+
*/
|
8
|
+
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <string.h>
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
|
14
|
+
#ifdef ENABLE_READLINE
|
15
|
+
#include <readline/readline.h>
|
16
|
+
#include <readline/history.h>
|
17
|
+
#define MIRB_ADD_HISTORY(line) add_history(line)
|
18
|
+
#define MIRB_READLINE(ch) readline(ch)
|
19
|
+
#define MIRB_WRITE_HISTORY(path) write_history(path)
|
20
|
+
#define MIRB_READ_HISTORY(path) read_history(path)
|
21
|
+
#define MIRB_USING_HISTORY() using_history()
|
22
|
+
#elif defined(ENABLE_LINENOISE)
|
23
|
+
#define ENABLE_READLINE
|
24
|
+
#include <linenoise.h>
|
25
|
+
#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
|
26
|
+
#define MIRB_READLINE(ch) linenoise(ch)
|
27
|
+
#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
|
28
|
+
#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
|
29
|
+
#define MIRB_USING_HISTORY()
|
30
|
+
#endif
|
31
|
+
|
32
|
+
#include "mruby.h"
|
33
|
+
#include "mruby/array.h"
|
34
|
+
#include "mruby/proc.h"
|
35
|
+
#include "mruby/compile.h"
|
36
|
+
#include "mruby/string.h"
|
37
|
+
|
38
|
+
#ifdef ENABLE_READLINE
|
39
|
+
|
40
|
+
static const char history_file_name[] = ".mirb_history";
|
41
|
+
|
42
|
+
static char *
|
43
|
+
get_history_path(mrb_state *mrb)
|
44
|
+
{
|
45
|
+
char *path = NULL;
|
46
|
+
const char *home = getenv("HOME");
|
47
|
+
|
48
|
+
#ifdef _WIN32
|
49
|
+
if (home != NULL) {
|
50
|
+
home = getenv("USERPROFILE");
|
51
|
+
}
|
52
|
+
#endif
|
53
|
+
|
54
|
+
if (home != NULL) {
|
55
|
+
int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
|
56
|
+
if (len >= 0) {
|
57
|
+
size_t size = len + 1;
|
58
|
+
path = (char *)mrb_malloc_simple(mrb, size);
|
59
|
+
if (path != NULL) {
|
60
|
+
int n = snprintf(path, size, "%s/%s", home, history_file_name);
|
61
|
+
if (n != len) {
|
62
|
+
mrb_free(mrb, path);
|
63
|
+
path = NULL;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
return path;
|
70
|
+
}
|
71
|
+
|
72
|
+
#endif
|
73
|
+
|
74
|
+
static void
|
75
|
+
p(mrb_state *mrb, mrb_value obj, int prompt)
|
76
|
+
{
|
77
|
+
mrb_value val;
|
78
|
+
|
79
|
+
val = mrb_funcall(mrb, obj, "inspect", 0);
|
80
|
+
if (prompt) {
|
81
|
+
if (!mrb->exc) {
|
82
|
+
fputs(" => ", stdout);
|
83
|
+
}
|
84
|
+
else {
|
85
|
+
val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if (!mrb_string_p(val)) {
|
89
|
+
val = mrb_obj_as_string(mrb, obj);
|
90
|
+
}
|
91
|
+
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
|
92
|
+
putc('\n', stdout);
|
93
|
+
}
|
94
|
+
|
95
|
+
/* Guess if the user might want to enter more
|
96
|
+
* or if he wants an evaluation of his code now */
|
97
|
+
static mrb_bool
|
98
|
+
is_code_block_open(struct mrb_parser_state *parser)
|
99
|
+
{
|
100
|
+
mrb_bool code_block_open = FALSE;
|
101
|
+
|
102
|
+
/* check for heredoc */
|
103
|
+
if (parser->parsing_heredoc != NULL) return TRUE;
|
104
|
+
if (parser->heredoc_end_now) {
|
105
|
+
parser->heredoc_end_now = FALSE;
|
106
|
+
return FALSE;
|
107
|
+
}
|
108
|
+
|
109
|
+
/* check for unterminated string */
|
110
|
+
if (parser->lex_strterm) return TRUE;
|
111
|
+
|
112
|
+
/* check if parser error are available */
|
113
|
+
if (0 < parser->nerr) {
|
114
|
+
const char unexpected_end[] = "syntax error, unexpected $end";
|
115
|
+
const char *message = parser->error_buffer[0].message;
|
116
|
+
|
117
|
+
/* a parser error occur, we have to check if */
|
118
|
+
/* we need to read one more line or if there is */
|
119
|
+
/* a different issue which we have to show to */
|
120
|
+
/* the user */
|
121
|
+
|
122
|
+
if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) {
|
123
|
+
code_block_open = TRUE;
|
124
|
+
}
|
125
|
+
else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
|
126
|
+
code_block_open = FALSE;
|
127
|
+
}
|
128
|
+
else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
|
129
|
+
code_block_open = FALSE;
|
130
|
+
}
|
131
|
+
return code_block_open;
|
132
|
+
}
|
133
|
+
|
134
|
+
switch (parser->lstate) {
|
135
|
+
|
136
|
+
/* all states which need more code */
|
137
|
+
|
138
|
+
case EXPR_BEG:
|
139
|
+
/* beginning of a statement, */
|
140
|
+
/* that means previous line ended */
|
141
|
+
code_block_open = FALSE;
|
142
|
+
break;
|
143
|
+
case EXPR_DOT:
|
144
|
+
/* a message dot was the last token, */
|
145
|
+
/* there has to come more */
|
146
|
+
code_block_open = TRUE;
|
147
|
+
break;
|
148
|
+
case EXPR_CLASS:
|
149
|
+
/* a class keyword is not enough! */
|
150
|
+
/* we need also a name of the class */
|
151
|
+
code_block_open = TRUE;
|
152
|
+
break;
|
153
|
+
case EXPR_FNAME:
|
154
|
+
/* a method name is necessary */
|
155
|
+
code_block_open = TRUE;
|
156
|
+
break;
|
157
|
+
case EXPR_VALUE:
|
158
|
+
/* if, elsif, etc. without condition */
|
159
|
+
code_block_open = TRUE;
|
160
|
+
break;
|
161
|
+
|
162
|
+
/* now all the states which are closed */
|
163
|
+
|
164
|
+
case EXPR_ARG:
|
165
|
+
/* an argument is the last token */
|
166
|
+
code_block_open = FALSE;
|
167
|
+
break;
|
168
|
+
|
169
|
+
/* all states which are unsure */
|
170
|
+
|
171
|
+
case EXPR_CMDARG:
|
172
|
+
break;
|
173
|
+
case EXPR_END:
|
174
|
+
/* an expression was ended */
|
175
|
+
break;
|
176
|
+
case EXPR_ENDARG:
|
177
|
+
/* closing parenthese */
|
178
|
+
break;
|
179
|
+
case EXPR_ENDFN:
|
180
|
+
/* definition end */
|
181
|
+
break;
|
182
|
+
case EXPR_MID:
|
183
|
+
/* jump keyword like break, return, ... */
|
184
|
+
break;
|
185
|
+
case EXPR_MAX_STATE:
|
186
|
+
/* don't know what to do with this token */
|
187
|
+
break;
|
188
|
+
default:
|
189
|
+
/* this state is unexpected! */
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
|
193
|
+
return code_block_open;
|
194
|
+
}
|
195
|
+
|
196
|
+
struct _args {
|
197
|
+
mrb_bool verbose : 1;
|
198
|
+
int argc;
|
199
|
+
char** argv;
|
200
|
+
};
|
201
|
+
|
202
|
+
/* Print a short remark for the user */
|
203
|
+
static void
|
204
|
+
print_hint(void)
|
205
|
+
{
|
206
|
+
printf("mirb - Embeddable Interactive Ruby Shell\n\n");
|
207
|
+
}
|
208
|
+
|
209
|
+
#ifndef ENABLE_READLINE
|
210
|
+
/* Print the command line prompt of the REPL */
|
211
|
+
static void
|
212
|
+
print_cmdline(int code_block_open)
|
213
|
+
{
|
214
|
+
if (code_block_open) {
|
215
|
+
printf("* ");
|
216
|
+
}
|
217
|
+
else {
|
218
|
+
printf("> ");
|
219
|
+
}
|
220
|
+
fflush(stdout);
|
221
|
+
}
|
222
|
+
#endif
|
223
|
+
|
224
|
+
void mrb_codedump_all(mrb_state*, struct RProc*);
|
225
|
+
|
226
|
+
static int
|
227
|
+
check_keyword(const char *buf, const char *word)
|
228
|
+
{
|
229
|
+
const char *p = buf;
|
230
|
+
size_t len = strlen(word);
|
231
|
+
|
232
|
+
/* skip preceding spaces */
|
233
|
+
while (*p && isspace((unsigned char)*p)) {
|
234
|
+
p++;
|
235
|
+
}
|
236
|
+
/* check keyword */
|
237
|
+
if (strncmp(p, word, len) != 0) {
|
238
|
+
return 0;
|
239
|
+
}
|
240
|
+
p += len;
|
241
|
+
/* skip trailing spaces */
|
242
|
+
while (*p) {
|
243
|
+
if (!isspace((unsigned char)*p)) return 0;
|
244
|
+
p++;
|
245
|
+
}
|
246
|
+
return 1;
|
247
|
+
}
|
248
|
+
|
249
|
+
/*static mrb_value*/
|
250
|
+
/*main(int argc, char **argv)*/
|
251
|
+
mrb_value
|
252
|
+
mrb_mruby_cli_mirb(mrb_state *mrb, mrb_value klass)
|
253
|
+
{
|
254
|
+
char ruby_code[1024] = { 0 };
|
255
|
+
char last_code_line[1024] = { 0 };
|
256
|
+
#ifndef ENABLE_READLINE
|
257
|
+
int last_char;
|
258
|
+
int char_index;
|
259
|
+
#else
|
260
|
+
char *history_path;
|
261
|
+
#endif
|
262
|
+
mrbc_context *cxt;
|
263
|
+
struct mrb_parser_state *parser;
|
264
|
+
/*mrb_state *mrb;*/
|
265
|
+
mrb_value result;
|
266
|
+
struct _args args;
|
267
|
+
mrb_bool code_block_open = FALSE;
|
268
|
+
int ai;
|
269
|
+
unsigned int stack_keep = 0;
|
270
|
+
|
271
|
+
#ifdef ENABLE_READLINE
|
272
|
+
history_path = get_history_path(mrb);
|
273
|
+
if (history_path == NULL) {
|
274
|
+
fputs("failed to get history path\n", stderr);
|
275
|
+
return mrb_fixnum_value(EXIT_FAILURE);
|
276
|
+
}
|
277
|
+
|
278
|
+
MIRB_USING_HISTORY();
|
279
|
+
MIRB_READ_HISTORY(history_path);
|
280
|
+
#endif
|
281
|
+
|
282
|
+
print_hint();
|
283
|
+
|
284
|
+
cxt = mrbc_context_new(mrb);
|
285
|
+
cxt->capture_errors = TRUE;
|
286
|
+
cxt->lineno = 1;
|
287
|
+
mrbc_filename(mrb, cxt, "(mirb)");
|
288
|
+
if (args.verbose) cxt->dump_result = TRUE;
|
289
|
+
|
290
|
+
ai = mrb_gc_arena_save(mrb);
|
291
|
+
|
292
|
+
while (TRUE) {
|
293
|
+
char *utf8;
|
294
|
+
|
295
|
+
#ifndef ENABLE_READLINE
|
296
|
+
print_cmdline(code_block_open);
|
297
|
+
|
298
|
+
char_index = 0;
|
299
|
+
while ((last_char = getchar()) != '\n') {
|
300
|
+
if (last_char == EOF) break;
|
301
|
+
if (char_index > sizeof(last_code_line)-2) {
|
302
|
+
fputs("input string too long\n", stderr);
|
303
|
+
continue;
|
304
|
+
}
|
305
|
+
last_code_line[char_index++] = last_char;
|
306
|
+
}
|
307
|
+
if (last_char == EOF) {
|
308
|
+
fputs("\n", stdout);
|
309
|
+
break;
|
310
|
+
}
|
311
|
+
|
312
|
+
last_code_line[char_index++] = '\n';
|
313
|
+
last_code_line[char_index] = '\0';
|
314
|
+
#else
|
315
|
+
char* line = MIRB_READLINE(code_block_open ? "* " : "> ");
|
316
|
+
if (line == NULL) {
|
317
|
+
printf("\n");
|
318
|
+
break;
|
319
|
+
}
|
320
|
+
if (strlen(line) > sizeof(last_code_line)-2) {
|
321
|
+
fputs("input string too long\n", stderr);
|
322
|
+
continue;
|
323
|
+
}
|
324
|
+
strcpy(last_code_line, line);
|
325
|
+
strcat(last_code_line, "\n");
|
326
|
+
MIRB_ADD_HISTORY(line);
|
327
|
+
free(line);
|
328
|
+
#endif
|
329
|
+
|
330
|
+
if (code_block_open) {
|
331
|
+
if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
|
332
|
+
fputs("concatenated input string too long\n", stderr);
|
333
|
+
continue;
|
334
|
+
}
|
335
|
+
strcat(ruby_code, last_code_line);
|
336
|
+
}
|
337
|
+
else {
|
338
|
+
if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) {
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
strcpy(ruby_code, last_code_line);
|
342
|
+
}
|
343
|
+
|
344
|
+
utf8 = mrb_utf8_from_locale(ruby_code, -1);
|
345
|
+
if (!utf8) abort();
|
346
|
+
|
347
|
+
/* parse code */
|
348
|
+
parser = mrb_parser_new(mrb);
|
349
|
+
if (parser == NULL) {
|
350
|
+
fputs("create parser state error\n", stderr);
|
351
|
+
break;
|
352
|
+
}
|
353
|
+
parser->s = utf8;
|
354
|
+
parser->send = utf8 + strlen(utf8);
|
355
|
+
parser->lineno = cxt->lineno;
|
356
|
+
mrb_parser_parse(parser, cxt);
|
357
|
+
code_block_open = is_code_block_open(parser);
|
358
|
+
mrb_utf8_free(utf8);
|
359
|
+
|
360
|
+
if (code_block_open) {
|
361
|
+
/* no evaluation of code */
|
362
|
+
}
|
363
|
+
else {
|
364
|
+
if (0 < parser->nerr) {
|
365
|
+
/* syntax error */
|
366
|
+
printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
|
367
|
+
}
|
368
|
+
else {
|
369
|
+
/* generate bytecode */
|
370
|
+
struct RProc *proc = mrb_generate_code(mrb, parser);
|
371
|
+
if (proc == NULL) {
|
372
|
+
fputs("codegen error\n", stderr);
|
373
|
+
mrb_parser_free(parser);
|
374
|
+
break;
|
375
|
+
}
|
376
|
+
|
377
|
+
if (args.verbose) {
|
378
|
+
mrb_codedump_all(mrb, proc);
|
379
|
+
}
|
380
|
+
/* pass a proc for evaulation */
|
381
|
+
/* evaluate the bytecode */
|
382
|
+
result = mrb_context_run(mrb,
|
383
|
+
proc,
|
384
|
+
mrb_top_self(mrb),
|
385
|
+
stack_keep);
|
386
|
+
stack_keep = proc->body.irep->nlocals;
|
387
|
+
/* did an exception occur? */
|
388
|
+
if (mrb->exc) {
|
389
|
+
p(mrb, mrb_obj_value(mrb->exc), 0);
|
390
|
+
mrb->exc = 0;
|
391
|
+
}
|
392
|
+
else {
|
393
|
+
/* no */
|
394
|
+
if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){
|
395
|
+
result = mrb_any_to_s(mrb, result);
|
396
|
+
}
|
397
|
+
p(mrb, result, 1);
|
398
|
+
}
|
399
|
+
}
|
400
|
+
ruby_code[0] = '\0';
|
401
|
+
last_code_line[0] = '\0';
|
402
|
+
mrb_gc_arena_restore(mrb, ai);
|
403
|
+
}
|
404
|
+
mrb_parser_free(parser);
|
405
|
+
cxt->lineno++;
|
406
|
+
}
|
407
|
+
|
408
|
+
#ifdef ENABLE_READLINE
|
409
|
+
MIRB_WRITE_HISTORY(history_path);
|
410
|
+
#endif
|
411
|
+
|
412
|
+
mrbc_context_free(mrb, cxt);
|
413
|
+
|
414
|
+
return mrb_fixnum_value(0);
|
415
|
+
}
|
data/src/mruby.c
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include "mruby.h"
|
5
|
+
#include "mruby/array.h"
|
6
|
+
#include "mruby/compile.h"
|
7
|
+
#include "mruby/dump.h"
|
8
|
+
#include "mruby/variable.h"
|
9
|
+
#include "mruby/compile.h"
|
10
|
+
#include "mruby/value.h"
|
11
|
+
#include "mruby/string.h"
|
12
|
+
|
13
|
+
#ifdef MRB_DISABLE_STDIO
|
14
|
+
static void
|
15
|
+
p(mrb_state *mrb, mrb_value obj)
|
16
|
+
{
|
17
|
+
mrb_value val = mrb_inspect(mrb, obj);
|
18
|
+
|
19
|
+
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
|
20
|
+
putc('\n', stdout);
|
21
|
+
}
|
22
|
+
#else
|
23
|
+
#define p(mrb,obj) mrb_p(mrb,obj)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
struct _args {
|
27
|
+
FILE *rfp;
|
28
|
+
char* cmdline;
|
29
|
+
mrb_bool fname : 1;
|
30
|
+
mrb_bool mrbfile : 1;
|
31
|
+
mrb_bool check_syntax : 1;
|
32
|
+
mrb_bool verbose : 1;
|
33
|
+
int argc;
|
34
|
+
char** argv;
|
35
|
+
};
|
36
|
+
|
37
|
+
static void
|
38
|
+
usage(const char *name)
|
39
|
+
{
|
40
|
+
static const char *const usage_msg[] = {
|
41
|
+
"switches:",
|
42
|
+
"-b load and execute RiteBinary (mrb) file",
|
43
|
+
"-c check syntax only",
|
44
|
+
"-e 'command' one line of script",
|
45
|
+
"-v print version number, then run in verbose mode",
|
46
|
+
"--verbose run in verbose mode",
|
47
|
+
"--version print the version",
|
48
|
+
"--copyright print the copyright",
|
49
|
+
NULL
|
50
|
+
};
|
51
|
+
const char *const *p = usage_msg;
|
52
|
+
|
53
|
+
printf("Usage: %s [switches] programfile\n", name);
|
54
|
+
while (*p)
|
55
|
+
printf(" %s\n", *p++);
|
56
|
+
}
|
57
|
+
|
58
|
+
static int
|
59
|
+
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
60
|
+
{
|
61
|
+
char **origargv = argv;
|
62
|
+
static const struct _args args_zero = { 0 };
|
63
|
+
|
64
|
+
*args = args_zero;
|
65
|
+
|
66
|
+
for (argc--,argv++; argc > 0; argc--,argv++) {
|
67
|
+
char *item;
|
68
|
+
if (argv[0][0] != '-') break;
|
69
|
+
|
70
|
+
if (strlen(*argv) <= 1) {
|
71
|
+
argc--; argv++;
|
72
|
+
args->rfp = stdin;
|
73
|
+
break;
|
74
|
+
}
|
75
|
+
|
76
|
+
item = argv[0] + 1;
|
77
|
+
switch (*item++) {
|
78
|
+
case 'b':
|
79
|
+
args->mrbfile = TRUE;
|
80
|
+
break;
|
81
|
+
case 'c':
|
82
|
+
args->check_syntax = TRUE;
|
83
|
+
break;
|
84
|
+
case 'e':
|
85
|
+
if (item[0]) {
|
86
|
+
goto append_cmdline;
|
87
|
+
}
|
88
|
+
else if (argc > 1) {
|
89
|
+
argc--; argv++;
|
90
|
+
item = argv[0];
|
91
|
+
append_cmdline:
|
92
|
+
if (!args->cmdline) {
|
93
|
+
size_t buflen;
|
94
|
+
char *buf;
|
95
|
+
|
96
|
+
buflen = strlen(item) + 1;
|
97
|
+
buf = (char *)mrb_malloc(mrb, buflen);
|
98
|
+
memcpy(buf, item, buflen);
|
99
|
+
args->cmdline = buf;
|
100
|
+
}
|
101
|
+
else {
|
102
|
+
size_t cmdlinelen;
|
103
|
+
size_t itemlen;
|
104
|
+
|
105
|
+
cmdlinelen = strlen(args->cmdline);
|
106
|
+
itemlen = strlen(item);
|
107
|
+
args->cmdline =
|
108
|
+
(char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
|
109
|
+
args->cmdline[cmdlinelen] = '\n';
|
110
|
+
memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
else {
|
114
|
+
printf("%s: No code specified for -e\n", *origargv);
|
115
|
+
return EXIT_SUCCESS;
|
116
|
+
}
|
117
|
+
break;
|
118
|
+
case 'v':
|
119
|
+
if (!args->verbose) mrb_show_version(mrb);
|
120
|
+
args->verbose = TRUE;
|
121
|
+
break;
|
122
|
+
case '-':
|
123
|
+
if (strcmp((*argv) + 2, "version") == 0) {
|
124
|
+
mrb_show_version(mrb);
|
125
|
+
}
|
126
|
+
else if (strcmp((*argv) + 2, "verbose") == 0) {
|
127
|
+
args->verbose = TRUE;
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
else if (strcmp((*argv) + 2, "copyright") == 0) {
|
131
|
+
mrb_show_copyright(mrb);
|
132
|
+
}
|
133
|
+
default:
|
134
|
+
return EXIT_FAILURE;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
if (args->rfp == NULL && args->cmdline == NULL) {
|
139
|
+
if (*argv == NULL) args->rfp = stdin;
|
140
|
+
else {
|
141
|
+
args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
|
142
|
+
if (args->rfp == NULL) {
|
143
|
+
printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
|
144
|
+
return EXIT_FAILURE;
|
145
|
+
}
|
146
|
+
args->fname = TRUE;
|
147
|
+
args->cmdline = argv[0];
|
148
|
+
argc--; argv++;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
|
152
|
+
memcpy(args->argv, argv, (argc+1) * sizeof(char*));
|
153
|
+
args->argc = argc;
|
154
|
+
|
155
|
+
return EXIT_SUCCESS;
|
156
|
+
}
|
157
|
+
|
158
|
+
mrb_value
|
159
|
+
mrb_mruby_cli_mruby(mrb_state *mrb, mrb_value klass)
|
160
|
+
{
|
161
|
+
int n = -1;
|
162
|
+
int i;
|
163
|
+
char *argv[255];
|
164
|
+
struct _args args;
|
165
|
+
mrb_value ARGV;
|
166
|
+
mrbc_context *c;
|
167
|
+
mrb_value v, array, element;
|
168
|
+
mrb_sym zero_sym;
|
169
|
+
mrb_int argc;
|
170
|
+
|
171
|
+
mrb_get_args(mrb, "io", &argc, &array);
|
172
|
+
|
173
|
+
for (i = 0; i < argc; i++) {
|
174
|
+
element = mrb_ary_shift(mrb, array);
|
175
|
+
argv[i] = RSTRING_PTR(element);
|
176
|
+
}
|
177
|
+
|
178
|
+
if (mrb == NULL) {
|
179
|
+
fputs("Invalid mrb_state, exiting mruby\n", stderr);
|
180
|
+
return mrb_fixnum_value(EXIT_FAILURE);
|
181
|
+
}
|
182
|
+
|
183
|
+
n = parse_args(mrb, argc, argv, &args);
|
184
|
+
if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
|
185
|
+
usage(argv[0]);
|
186
|
+
return mrb_fixnum_value(n);
|
187
|
+
}
|
188
|
+
|
189
|
+
ARGV = mrb_ary_new_capa(mrb, args.argc);
|
190
|
+
for (i = 0; i < args.argc; i++) {
|
191
|
+
char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
|
192
|
+
if (utf8) {
|
193
|
+
mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
|
194
|
+
mrb_utf8_free(utf8);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
mrb_define_global_const(mrb, "ARGV", ARGV);
|
198
|
+
|
199
|
+
c = mrbc_context_new(mrb);
|
200
|
+
if (args.verbose)
|
201
|
+
c->dump_result = TRUE;
|
202
|
+
if (args.check_syntax)
|
203
|
+
c->no_exec = TRUE;
|
204
|
+
|
205
|
+
/* Set $0 */
|
206
|
+
zero_sym = mrb_intern_lit(mrb, "$0");
|
207
|
+
if (args.rfp) {
|
208
|
+
const char *cmdline;
|
209
|
+
cmdline = args.cmdline ? args.cmdline : "-";
|
210
|
+
mrbc_filename(mrb, c, cmdline);
|
211
|
+
mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
|
212
|
+
}
|
213
|
+
else {
|
214
|
+
mrbc_filename(mrb, c, "-e");
|
215
|
+
mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
|
216
|
+
}
|
217
|
+
|
218
|
+
/* Load program */
|
219
|
+
if (args.mrbfile) {
|
220
|
+
v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
|
221
|
+
}
|
222
|
+
else if (args.rfp) {
|
223
|
+
v = mrb_load_file_cxt(mrb, args.rfp, c);
|
224
|
+
}
|
225
|
+
else {
|
226
|
+
char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
|
227
|
+
if (!utf8) abort();
|
228
|
+
v = mrb_load_string_cxt(mrb, utf8, c);
|
229
|
+
mrb_utf8_free(utf8);
|
230
|
+
}
|
231
|
+
|
232
|
+
mrbc_context_free(mrb, c);
|
233
|
+
if (mrb->exc) {
|
234
|
+
if (!mrb_undef_p(v)) {
|
235
|
+
mrb_print_error(mrb);
|
236
|
+
}
|
237
|
+
n = -1;
|
238
|
+
}
|
239
|
+
else if (args.check_syntax) {
|
240
|
+
printf("Syntax OK\n");
|
241
|
+
}
|
242
|
+
|
243
|
+
return n == 0 ? mrb_fixnum_value(EXIT_SUCCESS) : mrb_fixnum_value(EXIT_FAILURE);
|
244
|
+
}
|
data/tools/funky-cli/funky-cli.c
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
// This file is generated by mruby-cli. Do not touch.
|
2
2
|
#include <stdlib.h>
|
3
3
|
#include <stdio.h>
|
4
|
+
#include <string.h>
|
5
|
+
|
6
|
+
#include "mruby.h"
|
7
|
+
#include "mruby/compile.h"
|
8
|
+
#include "mruby/dump.h"
|
9
|
+
#include "mruby/proc.h"
|
4
10
|
|
5
11
|
/* Include the mruby header */
|
6
12
|
#include <mruby.h>
|
@@ -31,3 +37,4 @@ int main(int argc, char *argv[])
|
|
31
37
|
|
32
38
|
return return_value;
|
33
39
|
}
|
40
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: funky-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thiago Scalone
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -64,7 +64,14 @@ files:
|
|
64
64
|
- funky-cli.gemspec
|
65
65
|
- mrbgem.rake
|
66
66
|
- mrblib/funky-cli.rb
|
67
|
+
- mrblib/funky-cli/helper.rb
|
68
|
+
- mrblib/funky-cli/mruby.rb
|
69
|
+
- mrblib/funky-cli/setup.rb
|
67
70
|
- mrblib/funky-cli/version.rb
|
71
|
+
- mrblib/util.rb
|
72
|
+
- src/funky_cli_gem.c
|
73
|
+
- src/mirb.c
|
74
|
+
- src/mruby.c
|
68
75
|
- test/test_funky-cli.rb
|
69
76
|
- tools/funky-cli/funky-cli.c
|
70
77
|
homepage: http://github.com/da_funk/funky-cli
|