Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

AdventCalendar Day19 [超Ruby入門]

はじめに

本記事は、超Ruby入門19日目の記事です。

コメント頂ける方は、ガイドラインを読んで頂けると幸いです。

RHCとは

Ruby Hack Challenge(RHC)とは、Rubyコミッターが講師になってRubyの内部を触るという、いい感じのイベントです。

rubyhackchallenge

本題

RHCの演習を解説していきます。

MRI ソースコードの構造を参考にビルド等を行って下さい。

演習:バージョン表記の修正(改造)

まずは、ruby -v(もしくは ./miniruby -v)を実行したときに、自分の Ruby だとわかるように、何か表示を変えてみましょう。

これは、簡単ですね。

fflush(stdout);の前に、printf()で表示させるだけです。

workdir/ruby/version.c
void
ruby_show_version(void)
{
    if (MJIT_OPTS_ON) {
        PRINT(description_with_jit);
    }
    else {
        PRINT(description);
    }
#ifdef RUBY_LAST_COMMIT_TITLE
    fputs("last_commit=" RUBY_LAST_COMMIT_TITLE, stdout);
#endif
#ifdef HAVE_MALLOC_CONF
    if (malloc_conf) printf("malloc_conf=%s\n", malloc_conf);
#endif
    printf("imaharu\n");
    fflush(stdout);
}

最後に printf(...) を挟むだけではなく、ruby ... と書かれた行を変更しても面白いかもしれませんね。perl と出力してみるとか。

ruby 2.6.0dev ....
↓
Python 2.6.0dev ....

さて、Pythonと出力させるためにコードを追っていきましょう。

fflush(stdout);に注目します。fflushは、バッファに格納されているデータを吐き出すので、どこでデータが出力されているはずです。

怪しいのは、どう見てもPRINTですね。

workdir/ruby/version.c
    if (MJIT_OPTS_ON) {
        PRINT(description_with_jit);
    }
    else {
        PRINT(description);
    }

PRINTという文字をファイル内検索すると、関数が定義されていることが確認できました。

workdir/ruby/version.c
#define PRINT(type) puts(ruby_##type)
#define MKSTR(type) rb_obj_freeze(rb_usascii_str_new_static(ruby_##type, sizeof(ruby_##type)-1))
#define MKINT(name) INT2FIX(ruby_##name)

PRINT(type)の引数には、descriptionが与えられています。

descriptionは、RUBY_DESCRIPTION_WITHで生成されているようです。

workdir/ruby/version.c
const char ruby_description[] = RUBY_DESCRIPTION_WITH("");
static const char ruby_description_with_jit[] = RUBY_DESCRIPTION_WITH(" +JIT");

RUBY_DESCRIPTION_WITHは、version.cには、定義されていないので
includeされているファイルを確認して見ましょう。

workdir/ruby/version.c
#include "ruby/ruby.h"
#include "version.h"
#include "vm_core.h"
#include "mjit.h"
#include <stdio.h>

#include "version.h"が、いかにもな雰囲気を醸し出していますね。

workdir/ruby/version.h
# define RUBY_DESCRIPTION_WITH(opt) \
    "ruby "RUBY_VERSION         \
    RUBY_PATCHLEVEL_STR         \
    " ("RUBY_RELEASE_DATE       \
    RUBY_REVISION_STR")"opt" "      \
    "["RUBY_PLATFORM"]"
"ruby "RUBY_VERSION
↓
"Python "RUBY_VERSION

該当箇所を上記のように変更して、確認して見ましょう。

$pwd 
> /workdir/build
$ make miniruby
$./miniruby -v
Python 2.6.0dev .....

以上で演習:バージョン表記の修正(改造)の解説は終わりです。

深めたい人

興味のある人は、演習:メソッドの追加に挑戦してみましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?