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) {