Category ruby.

新しくなっているのに気付いた。 ruby extconf.rb --enable-error-handler (off by default) とか書いてあるのでちょっと期待しつつ。

とりあえず cygwin で make できんので Makefile 修正。OBJS に /lib/libxml2.dll.a /lib/libxslt.dll.a を追加して強制リンキング。exslt ははずす。

いろいろやってみたんだけど、よくわからん。USE_ERROR_HANDLERXML::XSLT.errors が定義されるんだけどエラー起こしても特に何も入ってない。/* this is really quite inelegant */ とか書いてあって苦労してんなぁとかなんとか。

とりあえずさらに really quite inelegant なコードで解決を図る。Ruby 側で…

require '../xslt'
xslt = XML::XSLT.new
xslt.xmlfile = "fuzface.xml"
xslt.xslfile = "fuzface.xsl"
begin
err = STDERR.dup
pipe = IO.pipe
STDERR.reopen(pipe[1])
out = xslt.serve # raise RuntimeError
rescue RuntimeError => e
p XML::XSLT.errors #=> []
if e.message =~ /^(XSL|XML|Stylesheet) /
p e
p pipe[0].readpartial(4096) #=> エラーメッセージ
else
raise
end
ensure
STDERR.reopen(err)
end
__END__
起こりうるエラーたち (grep)
parser.c:53:      rb_raise( rb_eRuntimeError, "XSL parsing error" );
parser.c:59:      rb_raise( rb_eRuntimeError, "XSL Stylesheet parsing error" );
parser.c:65:      rb_raise( rb_eRuntimeError, "XSL Stylesheet parsing error" );
parser.c:84:      rb_raise( rb_eRuntimeError, "XML parsing error" );
parser.c:90:      rb_raise( rb_eRuntimeError, "XML parsing error" );
parser.c:97:      rb_raise( rb_eRuntimeError, "Stylesheet transformation error" );

tests/fuzface.rb の改造。xmlfile= は使うなという警告がでるけどとりあえず放置。$stderr じゃなくて STDERR にメッセージを吐くらしくめんどっちいことをやってる。readpartial は cygwin の ruby が 1.8.3 になったから使ってみた。便利よねコレ

ごちゃごちゃやってみたけど使わない。XREA に入れるのめんどいし……

これでドウダ

class XML::XSLT
class XSLTError < StandardError; end
class XSLParsingError < XSLTError; end
class XSLStylesheetParsingError < XSLTError; end
class XMLParsingError < XSLTError; end
class StylesheetTransformationError < XSLTError; end
alias __org__serve serve
def serve
ret = nil
err = STDERR.dup
pipe = IO.pipe
Thread.critical = true
STDERR.reopen(pipe[1])
begin
ret = __org__serve
rescue RuntimeError => e
STDERR.reopen(err)
Thread.critical = false
message = pipe[0].sysread(4096)
error_class = XSLTError
case e.message
when "XSL parsing error"
error_class = XSLParsingError
when "XSL Stylesheet parsing error"
error_class = XSLStylesheetParsingError
when "XML parsing error"
error_class = XMLParsingError
when "Stylesheet transformation error"
error_class = StylesheetTransformationError
end
raise error_class.new(message)
ensure
STDERR.reopen(err)
Thread.critical = false
end
ret
end
end
xslt = XML::XSLT.new
xslt.xmlfile = "fuzface.xml"
xslt.xslfile = "fuzface.xsl"
begin
xslt.serve
rescue XML::XSLT::XSLTError => e
p e
end

将来完璧な実装になっても消すだけ! これなら使えそう? ごめん嘘。エラークラス云々があるのでそのままじゃ無理。

  1. トップ
  2. web
  3. ruby-xslt 0.8.2
  1. トップ
  2. ruby
  3. ruby-xslt 0.8.2
  1. トップ
  2. xslt
  3. ruby-xslt 0.8.2

make がうまくいったっぽいのでメモ。ちなみに数度要望の末 ruby-xslt を入れてもらってある (この過程で別の鯖と違う点があるかもしれない)。でもやっぱり自分でビルドできないかなぁという試行。

#!/bin/sh
PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:$PATH"
export PATH
ruby extconf.rb #1
#make #2
# test
#cd tests
#ruby fuzface.rb

みたいなのを make.sh として作って保存しとく。ちなみに AddHandler cgi-script-debug .sh してある。念のため一発でやらずに一行ずつ実行させる。

ruby extconf.rb は Permission Denied がでつつも一応通るので問題なしということにしとく。んで、make なんだけど libxml/* が見つからないとかいわれる。しかたないのでローカルの /usr/include/libxml2/libxml を同じディレクトリに転送する。エラー一切なく make が通った。テストもしてみたけど大丈夫っぽい。微妙だけど。

関係ないけど XREA に拡張ライブラリ置くとき怪しいことをすることにした。/virtual/username/lib/ruby/RUBY_PLATFORM を掘ってその中に入れる。ローカルは cygwin なので /virtual/username/lib/ruby/i386-cygwin/xml/xslt.so、XREA は /virtual/username/lib/ruby/i686-linux/xml/xslt.so。んで使う場合は $LOAD_PATH.unshift("/virtual/lowreal/lib/ruby", "/virtual/lowreal/lib/ruby/#{RUBY_PLATFORM}") しとく。もともと XREA 上の RSS パーサが古いのでアレしてコレした感じ。

s63.xrea.com 上で作った xslt.so。ちゃんと動くかは知らない。

ちなみに上のセクションのスクリプトは動かないです。1.8.2 なので。readpartial を sysread にすればとりあえず動きます。どっちでもよさげだから sysread にしとくのが吉か。

  1. トップ
  2. web
  3. ruby-xslt on XREA
  1. トップ
  2. xslt
  3. ruby-xslt on XREA
  1. トップ
  2. ruby
  3. ruby-xslt on XREA

寝たり起きたりするうちになんとなく実装したのがソレっぽく動いた。睡眠回数が多いほうがアイデアが浮かぶに違いない。

positive_mode = []
negative_mode = []
mode = positive_mode
arg_pos = 0
message[1].each_byte do |c|
case c
when ?+
mode = positive_mode
when ?-
mode = negative_mode
when ?o, ?v, ?k, ?l, ?b, ?e
mode << [c.chr, message[2+arg_pos]]
arg_pos += 1
else
mode << [c.chr, nil]
end
end
mode = nil
# when message is ["#chokan", "-o+v", "chokan", "chokan"]
p negative_mode #=> [["o", "chokan"]]
p positive_mode #=> [["v", "chokan"]]

うっさい

  1. トップ
  2. ruby
  3. IRC の MODE をパースするのがめんどい
  1. トップ
  2. irc
  3. IRC の MODE をパースするのがめんどい