summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/parse.y
diff options
context:
space:
mode:
authordearblue <[email protected]>2020-11-21 10:17:27 +0900
committerdearblue <[email protected]>2020-11-21 19:05:46 +0900
commita045b6b8d93f70d7bf57a94ed5c7e0432190d584 (patch)
tree54bdd026a2fbf6d6c6b607086f505ac75fdae1df /mrbgems/mruby-compiler/core/parse.y
parent55e127577863e0f913a4b7b8653fcba577c29b86 (diff)
downloadmruby-a045b6b8d93f70d7bf57a94ed5c7e0432190d584.tar.gz
mruby-a045b6b8d93f70d7bf57a94ed5c7e0432190d584.zip
Allow to mixed and specify `*.rb` and `*.mrb` in `bin/mruby`
It is not decides by the extension. In order to be recognized as a `.mrb` file, the following three points must be satisfied: - File starts with "RITE" - At least `sizeof(struct rite_binary_header)` bytes can be read - `NUL` is included in the first 64 bytes of the file If these are not met, it is judged as a text file and it is processed as a Ruby script. The `bin/mruby -b` switch is still available which treats the given file as a `.mrb` file. New `MRB_API` function: - `include/mruby/compile.h` and `mrbgems/mruby-compiler/core/parse.y` - `mrb_load_detect_file_cxt()` (remove with `MRB_DISABLE_STDIO`) NOTE: - Even script files now always open in binary mode for `bin/mruby`. The `\r\n` is handled by the `nextc()` function already, so there is no problem even on Windows. - The `nextc0()` function in `mrbgems/mruby-compiler/core/parse.y` can now specify a string buffer and a file pointer at the same time. In this case, get it from the string buffer first. This patch includes modifies by comment of https://github.com/mruby/mruby/pull/5157.
Diffstat (limited to 'mrbgems/mruby-compiler/core/parse.y')
-rw-r--r--mrbgems/mruby-compiler/core/parse.y85
1 files changed, 71 insertions, 14 deletions
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 0c4d83fbc..d6271f354 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -21,6 +21,7 @@
#include <mruby/error.h>
#include <mruby/throw.h>
#include <mruby/string.h>
+#include <mruby/dump.h>
#include "node.h"
#define YYLEX_PARAM p
@@ -4122,20 +4123,20 @@ static inline int
nextc0(parser_state *p)
{
int c;
-#ifndef MRB_DISABLE_STDIO
- if (p->f) {
- if (feof(p->f)) return -1;
- c = fgetc(p->f);
- if (c == EOF) return -1;
+
+ if (p->s && p->s < p->send) {
+ c = (unsigned char)*p->s++;
}
- else
+ else {
+#ifndef MRB_DISABLE_STDIO
+ if (p->f) {
+ c = fgetc(p->f);
+ if (feof(p->f)) return -1;
+ }
+ else
#endif
- if (!p->s || p->s >= p->send) {
return -1;
- }
- else {
- c = (unsigned char)*p->s++;
- }
+ }
return c;
}
@@ -6520,19 +6521,26 @@ mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
}
#ifndef MRB_DISABLE_STDIO
-MRB_API parser_state*
-mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
+static struct mrb_parser_state *
+mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t prebufsize, mrbc_context *c)
{
parser_state *p;
p = mrb_parser_new(mrb);
if (!p) return NULL;
- p->s = p->send = NULL;
+ p->s = (const char *)prebuf;
+ p->send = (const char *)prebuf + prebufsize;
p->f = f;
mrb_parser_parse(p, c);
return p;
}
+
+MRB_API parser_state*
+mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
+{
+ return mrb_parse_file_continue(mrb, f, NULL, 0, c);
+}
#endif
MRB_API parser_state*
@@ -6629,6 +6637,55 @@ mrb_load_file(mrb_state *mrb, FILE *f)
{
return mrb_load_file_cxt(mrb, f, NULL);
}
+
+#define DETECT_SIZE 64
+
+/*
+ * In order to be recognized as a `.mrb` file, the following three points must be satisfied:
+ * - File starts with "RITE"
+ * - At least `sizeof(struct rite_binary_header)` bytes can be read
+ * - `NUL` is included in the first 64 bytes of the file
+ */
+MRB_API mrb_value
+mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c)
+{
+ union {
+ char b[DETECT_SIZE];
+ struct rite_binary_header h;
+ } leading;
+ size_t bufsize;
+
+ if (mrb == NULL || fp == NULL) {
+ return mrb_nil_value();
+ }
+
+ bufsize = fread(leading.b, sizeof(char), sizeof(leading), fp);
+ if (bufsize < sizeof(leading.h) ||
+ memcmp(leading.h.binary_ident, RITE_BINARY_IDENT, sizeof(leading.h.binary_ident)) != 0 ||
+ memchr(leading.b, '\0', bufsize) == NULL) {
+ return mrb_load_exec(mrb, mrb_parse_file_continue(mrb, fp, leading.b, bufsize, c), c);
+ }
+ else {
+ size_t binsize;
+ uint8_t *bin;
+ mrb_value bin_obj = mrb_nil_value(); /* temporary string object */
+ mrb_value result;
+
+ binsize = bin_to_uint32(leading.h.binary_size);
+ bin_obj = mrb_str_new(mrb, NULL, binsize);
+ bin = (uint8_t *)RSTRING_PTR(bin_obj);
+ memcpy(bin, leading.b, bufsize);
+ if (binsize > bufsize &&
+ fread(bin + bufsize, binsize - bufsize, 1, fp) == 0) {
+ binsize = bufsize;
+ /* The error is reported by mrb_load_irep_buf_cxt() */
+ }
+
+ result = mrb_load_irep_buf_cxt(mrb, bin, binsize, c);
+ if (mrb_string_p(bin_obj)) mrb_str_resize(mrb, bin_obj, 0);
+ return result;
+ }
+}
#endif
MRB_API mrb_value