summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-02-08 13:56:05 -0500
committerKevin Newton <kddnewton@gmail.com>2024-02-08 14:36:29 -0500
commit3ecfc3e33ef7db8e9f855490910077ac7ed13434 (patch)
tree247da8ee2c21d7e9cd859fec9f9167a772676fc9
parent1936278461cf9aec1495596bf25a2963721f21ee (diff)
[PRISM] Support the DATA constant
-rw-r--r--prism/prism.c1
-rw-r--r--ruby.c15
2 files changed, 16 insertions, 0 deletions
diff --git a/prism/prism.c b/prism/prism.c
index 22503fd726..9df29a2de5 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -17791,6 +17791,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
.current = { .type = PM_TOKEN_EOF, .start = source, .end = source },
.next_start = NULL,
.heredoc_end = NULL,
+ .data_loc = { .start = NULL, .end = NULL },
.comment_list = { 0 },
.magic_comment_list = { 0 },
.warning_list = { 0 },
diff --git a/ruby.c b/ruby.c
index b0bce7216b..2e95b37173 100644
--- a/ruby.c
+++ b/ruby.c
@@ -2423,6 +2423,21 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
}
else {
error = pm_parse_file(&result, opt->script_name);
+
+ // If we found an __END__ marker, then we're going to define a
+ // global DATA constant that is a file object that can be read
+ // to read the contents after the marker.
+ if (error == Qnil && result.parser.data_loc.start != NULL) {
+ int xflag = opt->xflag;
+ VALUE file = open_load_file(opt->script_name, &xflag);
+
+ size_t offset = result.parser.data_loc.start - result.parser.start + 7;
+ if ((result.parser.start + offset < result.parser.end) && result.parser.start[offset] == '\r') offset++;
+ if ((result.parser.start + offset < result.parser.end) && result.parser.start[offset] == '\n') offset++;
+
+ rb_funcall(file, rb_intern("seek"), 2, LONG2NUM(offset), INT2FIX(SEEK_SET));
+ rb_define_global_const("DATA", file);
+ }
}
if (error == Qnil) {