-
完全対応する必要はない
luaもそうですが、cp932に対応といっても、フルに対応する必要はありません。
いわば、「バイト列」としての扱いのまま、cp932文字コードで「エラー」が出ない状態であれば十分と言えます。
いわゆるLuaのcp932化と同じレベルものものを目指します。
-
mbenc.hの作成
まず、mbenc.hというファイルを作ります。
/*
** mbenc.h : MS-Windows用マクロ
**
** mruby の cp932 encoding用
** by 翔.jp
*/
#ifndef mbenc_h
#define mbenc_h
#define MRUBY_USE_ENC_CP932 1
/* -- japanese cp932 -- */
#if MRUBY_USE_ENC_CP932
#define is_lead_byte(c) ((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f) || (0xe0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <=0xfc))
#else
#define is_lead_byte(c) (0)
#endif
#endif
このファイルをmrubyの「\mruby-master\include」ディレクトリの中に入れましょう。
-
parse.yの編集
次に、parse.yというファイルが、mruby-master\src\parse.y という場所にあります。
static int
parse_string(parser_state *p)
の関数のwhile文内の一番下あたりが、
pushback(p, c);
return tLITERAL_DELIM;
}
else {
pushback(p, c);
tokfix(p);
yylval.nd = new_str(p, tok(p), toklen(p));
return tSTRING_MID;
}
}
tokadd(p, c);
}
tokfix(p);
p->lstate = EXPR_END;
end_strterm(p);
if (type & STR_FUNC_XQUOTE) {
のようになっていますので、
(※バージョンが違うと少々違うかもしれませんが、とりあえず似た場所があるはずです)
pushback(p, c);
return tLITERAL_DELIM;
}
else {
pushback(p, c);
tokfix(p);
yylval.nd = new_str(p, tok(p), toklen(p));
return tSTRING_MID;
}
}
{
int is_cp932 = 0; /* cp932用 */
if ( is_lead_byte( c ) ) { /* cp932の範囲だったらフラグ立て */
is_cp932 = 1;
}
tokadd(p, c); // 文字コードに関わりない処理。
if ( is_cp932 && c != EOF ) { /* cp932の範囲だったらもうひとつ無条件で処理してしまう */
c = nextc(p);
tokadd(p, c);
is_cp932 = 0;
}
}
}
tokfix(p);
p->lstate = EXPR_END;
end_strterm(p);
if (type & STR_FUNC_XQUOTE) {
と書き換えます。
同じファイルの先頭のヘッダー部分に
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
#include "mruby/error.h"
#include "node.h"
#include "mrb_throw.h"
#include "mbenc.h" // for cp932
を足しておきましょう。
-
VC++ 2013のコンパイルオプション
さて、Windowsでは通常、VisualStudioでプログラミングするでしょう。
その場合、mrubyはVC++ Desktop 2013以上でコンパイルすることとなります。
さて、それを踏まえて
mruby-master\tasks\toolchains\visualcpp.rake
を開けて、以下の強調してる行のオプションを変更します。
MRuby::Toolchain.new(:visualcpp) do |conf|
[conf.cc].each do |cc|
cc.command = ENV['CC'] || 'cl.exe'
# C4013: implicit function declaration
cc.flags = [ENV['CFLAGS'] || %w(/c /nologo /W3 /we4013 /Zi /MT /Ox /Oi /Ot /D_CRT_SECURE_NO_WARNINGS)]
cc.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING)
cc.option_include_path = '/I%s'
cc.option_define = '/D%s'
cc.compile_options = "%{flags} /Fo%{outfile} %{infile}"
end
[conf.cxx].each do |cxx|
cxx.command = ENV['CXX'] || 'cl.exe'
cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MT /Ox /Oi /Ot /EHsc /D_CRT_SECURE_NO_WARNINGS)]
VC++ Desktop2013の「VS2013 x86 Native Tools コマンド プロンプトを開く」を使います。
VC++ Desktop2013 ではショートカットが存在しない場合がありますので、無い場合は自分で制作しましょう。
デスクトップにショートカットを作成して、
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 13.0\VC\vcvarsall.bat"" x86
みたいなのを作成します。
実際には、VC++2013をインストールしたディレクトリにあわせて書き換えてください。
-
先述のVC専用コンソールに話を戻して、コンソールを立ち上げて、
そこまで、ディレクトリを移動してから、

ruby ./minirake