c-repl - C言語のREPL
http://neugierig.org/software/c-repl/
便利そう。ただ、実際の開発で使うためにはオブジェクトファイルをロードできないとだめかも!?
gdcはgccベースのD言語コンパイラなのでD言語にも対応できるかも?
$ cd ~/src; darcs get http://neugierig.org/software/darcs/c-repl
でインストール。
$ ./repl > .h math.h .h math.h > .l m .l m > printf("%g\n", sin(1.0)) printf("%g\n", sin(1.0)) 0.841471
オブジェクトファイル対応化。環境変数によるヘッダファイル・オブジェクトファイル・ライブラリ指定
というわけでさっそく*.oも読み込めるようにhack。3行加えるだけ。
ついでにヘッダファイルやライブラリやオブジェクトファイルを毎回指定するなんてやってられないので環境変数で指定できるようにした。3行変更。
Rubyの部分はきれいに書かれているので改良は容易だった。
--- repl 2007/10/03 22:46:48 1.1 +++ repl 2007/10/03 23:33:50 @@ -63,8 +63,9 @@ @cur_so_id = 1 @runner = Runner.new @externs = [] - @headers = [] - @libraries = [] + @headers = (ENV['REPL_HEADERS']||"").split + @libraries = (ENV['REPL_LIBS']||"").split + @objs = (ENV['REPL_OBJS']||"").split @commands = { 'd' => ['toggle debug mode.', proc { @debug = !@debug; puts "debug is #{@debug?'on':'off'}" }], @@ -94,11 +95,11 @@ writer.close STDIN.reopen(reader) reader.close - cmd = "gcc -xc -g -shared -o #{name}.so" + cmd = "gcc -xc -g -I. -c - -o tmp.o && gcc -L. -g -shared -o #{name}.so tmp.o " # add in all libraries cmd += ' ' + @libraries.map{|l| "-l#{l}"}.join(' ') - # tell it to read input through stdin - cmd += ' -' + # add in all objects + cmd += ' ' + @objs.map{|o| "#{o}"}.join(' ') puts cmd if @debug exec(cmd) end
さて、実行結果は。
~/src/c-repl% cat hoge.c int add(int x, int y) { return x+y; } ~/src/c-repl% cat hoge.h int add(int x, int y); ~/src/c-repl% REPL_LIBS=m REPL_OBJS=hoge.o REPL_HEADERS="math.h hoge.h" ./repl > printf("%g\n", sin(1.0)) 0.841471 > printf("%d\n", add(1,2)) 3
作者へフィードバック
せっかくdarcsを使っているのだから作者にパッチ送付。
darcs record darcs send -o mypatch
最後にmypatchを添付して作者にメール。
インストール
インストールするためには名前を変えておいたほうがいい。このへんいい加減。他のディレクトリで実行することを考慮していないのは明らかなので、実際のプログラムをhackするのに使われているかどうか怪しい。
まず、カレントのchildを実行するようハードコードされているので修正。
--- repl 2007/10/03 23:53:19 1.2 +++ repl 2007/10/03 23:53:23 @@ -20,7 +20,7 @@ response_pipe[0].close STDIN.reopen(command_pipe[0]) command_pipe[0].close - exec('./child', response_pipe[1].fileno.to_s) + exec('c-repl-child', response_pipe[1].fileno.to_s) end command_pipe[0].close command_pipe[1].sync = true
インストールの例。俺の場合~/binにPATHが通っていてRUBYLIBに~/rubyを指定してあるのでこんな感じ。
$ mv child c-repl-child $ cp repl ~/bin; cp c-repl-child ~/bin; cp codesnippet.rb gdbmi.rb ~/ruby