change indent. (no meaning.)
authoreto <eto>
Wed, 12 Mar 2003 08:32:00 +0000 (08:32 +0000)
committereto <eto>
Wed, 12 Mar 2003 08:32:00 +0000 (08:32 +0000)
src/chise.rb

index 4eef060..084a24e 100755 (executable)
@@ -97,12 +97,12 @@ class String #==================================================================
     }
     str = ""
     h.each {|k, v|
-#      p [k, v]
+      #      p [k, v]
       if length == v #全部に顔を出していたら
        str += k
       end
     }
-#    p str
+    #    p str
     str
   end
   def compose()
@@ -118,15 +118,15 @@ class String #==================================================================
     return "" #attributeを持つものが一つも無かったら、""にする
   end
   def aggregate()
-#selfである文字列をIDSだと仮定し、それを完全にcomposeしきらないで、
-#その部分集合だけをとりだして、compose可能であればできるだけcomposeする。
+    #selfである文字列をIDSだと仮定し、それを完全にcomposeしきらないで、
+    #その部分集合だけをとりだして、compose可能であればできるだけcomposeする。
     tree = IDS_Tree.new(self)
     return self if tree.depth <= 1 #sub_nodesが無い場合はここでさよなら
     tree.sub_nodes.each {|node|
       c = node.compose
       next if c.nil? || c == ""
-#      print "#{self}  #{node} #{c}\n"
-#      p [self, node, c]
+      #      print "#{self}    #{node} #{c}\n"
+      #      p [self, node, c]
       n = self.gsub(node, c)
       return n.aggregate
     }
@@ -178,7 +178,7 @@ module CHISE #==================================================================
       return "" unless er =~ Regexp.new(REGEXP_ALL) #なんか、間違ってる?
       er = $1 #ついでに中身の部分を取り出す
       return $1.hex if er =~ /^MCS-([0-9A-Fa-f]+)/ #MCS
-#      if er =~ /^U[-+]?([0-9A-Fa-f]+)/ #Unicode直打ち
+      #      if er =~ /^U[-+]?([0-9A-Fa-f]+)/ #Unicode直打ち
       if er =~ /^U[-+]?([0-9A-Fa-f]+)/ || er =~ /^#x([0-9A-Fa-f]+)/ #Unicode直打ち
        return $1.hex 
       end
@@ -385,481 +385,496 @@ module CHISE #==================================================================
       ar = %w{ucs-jis ucs =>ucs-jis}
       #並び順は恣意的で、ucs-jisを先に出している。本来はこれも指定できるようにするべき。
       ar.each {|a|     #p [a]
-        u = get_char_attribute(a)
-        return u if u != nil
-       }
-       return nil
-     end
-
-     #----------------------------------------------------------------------CCS関係
-     def to_utf8() Uconv.u4tou8(Character.u4itou4(ucs())) end #UTF8文字列を返す
-     #alias to_s to_utf8
-     alias to_s mcs_utf8
-     def map_utf8()
-       u = ucs()
-       if u.nil? || 0xffff < u
-        return to_er()
-       else
-        return to_utf8()
-       end
-     end
-     alias map_ucs map_utf8
-     def map_ucs_er()
-       u = ucs()
-       if u.nil? || 0xffff < u
-        return to_er()
-       else
-        return Character.get(u).to_er()
-       end
-     end
-     def to_euc()
-       u = ucs()
-       return "" if u.nil? || 0xffff < u
-       Uconv.u16toeuc(Uconv.u4tou16(Character.u4itou4(ucs())))
-     end
-     def map_euc()
-       e = to_euc()
-       return e if e != ""
-       return to_er()
-     end
-     def to_sjis()
-       u = ucs()
-       return "" if u.nil? || 0xffff < u
-       Uconv.u16tosjis(Uconv.u4tou16(Character.u4itou4(ucs())))
-     end
-     def map_sjis()
-       e = to_sjis()
-       return e if e != ""
-       return to_er()
-     end
-
-     #----------------------------------------------------------------------
-     def to_er(codesys=nil) #実体参照を返す、希望するcodesysが引数(未実装)
-       return "" if @char_id == nil
-       return sprintf("&#x%04x;", @char_id) if @char_id <= 0xffff
-       return sprintf("&#x%05x;", @char_id) if @char_id <= 0xfffff
-       EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
-        code = self[codesys]
-        next if code == nil
-        return sprintf("&#{er_prefix}%0#{keta}#{numtype};", code)
-       }
-       return sprintf("&MCS-%08X;", @char_id) #本当はこれは無しにしたい
-     end
-     def to_er_list()
-       ar = []
-       EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
-        er = to_er(codesys)
-        ar << er if er != nil
-       }
-       ar
-     end
-
-     def inspect_x()
-       return "<>" if @char_id == nil
-       ar = [to_utf8(), to_er().sub(/^&/,'').chop]
-       "<"+ar.join(',')+">"
-     end
-     alias inspect inspect_x
-     def inspect_all_codesys() #未完成
-       #to_erを全てのcodesysにおいて実行する。その結果をコンパクトにまとめる
-     end
-     def inspect_all()
-       ar = [inspect.chop]
-       alist.to_a.sort.each {|a, v| ar << "#{a}:#{v}" }
-       return ar.join(',')+">"
-     end
-     def get_attributes()
-       str = ""
-       alist.to_a.sort.each {|a, v|
-        str += "#{a}: #{v}\n"
-       }
-       str
-     end
-
-     def inspect_ids(hex_flag=false)
-       ids = decompose
-       ar = []
-       ar << (hex_flag ? "x"+mcs_hex : to_utf8)
-       if to_s != ids #idsが部品そのものだったら部品追加はしない
-        ids.each_char {|ch|
-          char = ch.char
-          next if char.is_ids?
-          if hex_flag then
-            ar << "x"+char.mcs_hex
-          else
-            u = char.to_utf8
-            if u != ""
-              ar << u
-            else
-              ar << char.to_er
-            end
-          end
-         }
-       end
-       return "("+ar.join("\t")+")"
-     end
-
-     #----------------------------------------------------------------------IDS関係
-     def decompose
-       k = self.to_s
-#       idss = self['ids']
-#       return idss if idss
-#       return k if self.is_basic_kanji? #基本漢字はstop kanjiとするぞと。
-       return self['ids-represent'] if self['ids-represent'] #ids_representを持っている場合はその値とする。
-       return self['ids-element'] if self['ids-element'] #ids_elementを持っている場合はその値とする。
-
-       idss = self['ids-meaning']
-       return idss if idss != nil && 0 < idss.length && k != idss
-       idss = self['ids-aggregated']
-       return idss if idss != nil && 0 < idss.length && k != idss
-       idss = self['ids']
-       return idss if idss != nil && 0 < idss.length && k != idss
-       return k
-#       return k if idss.nil? || idss.length == 0 || k == idss
-#       if idss.char_length == 2
-#      p ['What???', k, idss, k.inspect_all]
-#       #return idssx[1] #二個目だけ返すとか?
-#       return k #IDSに展開する方法が無いと。
-#       end
-#       return k if k == idss
-#       if idss.include?(k) #<C5-4C4D><C6-4A37>この二文字のBUG対策
-#       #return idss.sub(k, '')
-#       return k #IDSに展開する方法が無いと。
-#       end
-#       return idss
-     end
-     def decompose_all
-       pde = ""
-       de = self.decompose #出発点
-       level = 0
-       while true
-        pde = de
-        de = pde.decompose #もう一度分解をしてみる。
-        break if pde == de #ループを抜けだす
-        exit if 10 < level #p ['too many recursive', self] 
-        level += 1
-       end
-       return de
-     end
-     def decompose_all_nu(level=nil)
-       level = 0 if level.nil?
-       if 10 < level
-        p ['too many recursive', self] 
-        exit
-       end
-       de = self.decompose
-       return de.decompose_all(level+1) if de != self #なにか変化があったから再帰
-       return de #もうこれ以上変化は無さそうだぞと。
-     end
-     def is_ids?() 0x2ff0 <= @char_id && @char_id <= 0x2fff end
-     def ids_operator_argc()
-       return 0 unless is_ids?
-       return 3 if @char_id == 0x2ff2 || @char_id == 0x2ff3
-       return 2
-     end
-   end
-
-   class DBS #======================================================================複数のDBを集めたclass、未完成
-   end
-
-   class ADB < BDB::Hash #======================================================================一つのDB
-     def initialize(*args)
-       super
-       @modified = false
-       at_exit {
-        if @modified
-          self.close #これがないと、うまくデータベースがセーブされないのです。
-        end
-       }
-     end
-     def self.open_create(filename)
-       ADB.open(filename, nil, BDB::CREATE | BDB::EXCL) #上書きはしない
-     end
-     def mykey(key)
-       if key.is_a?(String)
-        if key.char_length == 1
-          return '?'+key  #Stringだったら引く前に?を足す
-        end
-       end
-       #key = key.to_s if key.is_a?(Numeric) #NumberだったらStringにする。
-       #ここで && key ! =~ /^\?/ をいれると、?自身を検索できなくなってしまう。
-       return key
-     end
-     def myvalue(v)
-       return v if v == nil
-       return v.to_i if v =~ /^\d+$/ #数字だったらここで変換しておく
-       return v.sub(/^\?/, '') if v =~ /^\?/ #冒頭の?は取り除く
-       return $1 if v =~ /^"(.+)"$/ #最初と最後に"がついていたら、取り除く
-       #p ['get', v, t, key, db]
-       #return parse_sexp(v) if v =~ /^\(.+\)$/ #最初と最後が()の時は、S式にparseする
-       return v #それ以外って何?
-     end
-     def myget(key) #keyキーを引いて返す
-       key = mykey(key)
-       v = get(key) #存在しなかったらnilを返すことになる
-       return myvalue(v)
-     end
-     def myput(key, v) #keyにvをいれる
-       key = mykey(key)
-       put(key, v) #putする
-       @modified = true
-     end
-   end
-
-   class DB #======================================================= データベース群のabstract class
-     def self.unix_to_win(unix) #Windowsファイル名制限のため、変換する
-       win = unix.gsub(/</, '(')
-       win.gsub!(/>/, ')')
-       win.gsub!(/\*/, '+')
-       win.gsub!(/\?/, '!')
-       return win
-     end
-     def self.win_to_unix(win)
-       unix = win.gsub(%r|\)|, '>')
-       unix.gsub!(%r|\(|, '<')
-       unix.gsub!(%r|!|, '?')
-       unix.gsub!(%r|\+|, '*')
-       return unix
-     end
-     def get_filename(t)
-       return @pre + DB.unix_to_win(t) + @post if windows?
-       return @pre + t + @post
-     end
-     def get_dirname(t) File.dirname(get_filename(t)) end
-     def open_dbs()
-       @dbs = Hash.new
-       keys = find_keys()
-       keys.each {|key| open_db(key) }
-     end
-     def find_keys()
-       files = []
-       Dir.glob(@glob){|f|
-        next if ! File.file?(f)
-        next if f =~ /.txt$/
-        files << f
-       }
-       keys = []
-       files.each {|f|
-        t = DB.win_to_unix(f)
-        t.sub!(%r|^#{@pre}|, '')
-        t.sub!(%r|#{@post}$|, '') if @post != ""
-        keys << t
-       }
-       return keys
-     end
-     def close_db(t)
-       db = get(t)
-       return nil if db.nil?
-       db.close
-       @dbs.delete(t)
-     end
-     def open_db(t)
-       return nil if get(t) #すでにopenしていたら再openはしない。
-       begin
-        bdb = ADB.open(get_filename(t), nil, 0)
-        @dbs[t] = bdb if bdb != nil
-       rescue
-        p ["open error", get_filename(t)]; return nil
-       end
-       return true
-     end
-     def make_db(t, h=nil) #tという名前でhという中身のデータベースを作る
-       return nil if get(t) #すでにある場合はreturn
-       Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
-       db = nil
-       begin
-        db = ADB.open_create(get_filename(t)) #上書きはしない
-        if h != nil
-          h.each {|k, v|
-            k = '?'+k if k.is_a?(String)
-            db[k] = v
-          }
-        end
-        db.close
-       rescue
-        p ["make error", get_filename(t)]; return nil
-       end
-       return true
-     end
-     def make_db_no_question_mark(t, h=nil) #tという名前でhという中身のデータベースを作る
-       return nil if get(t) #すでにある場合はreturn
-       Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
-       db = nil
-       begin
-        db = ADB.open_create(get_filename(t)) #上書きはしない
-        if h != nil
-          h.each {|k, v|
-#           k = '?'+k if k.is_a?(String)
-            db[k] = v
-          }
-        end
-        db.close
-       rescue
-        p ["make error", get_filename(t)]; return nil
-       end
-       return true
-     end
-     def remove_db(t) #tという名前のデータベースを消去する
-       db = get(t)
-       if db
-        db.close
-        @dbs.delete(t)
-       end
-       begin
-        File.unlink(get_filename(t)) if FileTest.file?(get_filename(t))
-       rescue
-        p ["unlink error", get_filename(t)]; return nil
-       end
-       dn = get_dirname(t)
-       Dir.rmdir(dn) if FileTest.directory?(dn) && Dir.entries(dn).length <= 2 #空directoryだったら消す
-       return true
-     end
-     def to_num(s)
-       return s.to_i if s =~ /^\d+$/
-       return s
-     end
-     def dump_db(t)
-       db = get(t)
-       return nil unless db
-       file = get_filename(t)
-       open("#{file}.txt", "w"){|out|
-#       out.binmode.sync = true
-        ar = db.to_a
-        ar.map! {|k, v| [to_num(k), to_num(v)] }
-        ar.sort.each {|k, v|
-          out.printf("%s\t%s\n", k, v)
-        }
-       }
-       return true
-     end
-     def each_db()  @dbs.to_a.sort.each {|t, db| yield(t, db) } end
-     def dump_all()  each_db {|t, db| dump_db(t) } end
-     def close_all() each_db {|t, db| db.close   } end
-     def keys() @dbs.keys end
-     def each(t)
-       return unless block_given?
-       db = @dbs[t]
-       return nil unless db
-       db.each {|k, v|
-        k = to_num(k)
-        v = to_num(v)
-        k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
-        vv = get(t, k) #p ['each', t, k, v, vv]
-        yield(k, vv)
-       }
-     end
-     def each_sort(t)
-       return unless block_given?
-       db = @dbs[t]
-       return nil unless db
-       ar = db.to_a
-       ar.map! {|k, v| [to_num(k), to_num(v)] }
-       ar.sort.each {|k, v|
-        k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
-        vv = get(t, k) #p ['each', t, k, v, vv]
-        yield(k, vv)
-       }
-     end
-     #----------------------------------------------------------------------
-     def get(t, key=nil) #tというデータベースのkeyキーを引いて返す
-       db = @dbs[t]
-       return db if key.nil?
-       return nil unless db
-       return db.myget(key)
-     end
-     def put(t, key, v) #tというデータベースのkeyにvをいれる
-       db = @dbs[t]
-       if db == nil
-        db = make_db(t) 
-        db = open_db(t) 
-        db = @dbs[t]
-       end
-       db.myput(key, v) #putする
-     end
-   end
-
-   class CharDB < DB #------------------------------------ MCS-UTF8をキーとした属性へのデータベース
-     include Singleton
-     def initialize()
-       super
-       @glob, @pre, @post = "#{DB_DIR}/system-char-id/*", "#{DB_DIR}/system-char-id/", ""
-       open_dbs()
-     end
-     def get_all(u8) #全データベースのu8キーを引いてHashにまとめて返す
-       atrs = Hash.new
-       @dbs.each {|t, db|
-        v = get(t, u8)
-        atrs[t] = v if v != nil
-       }
-       return atrs
-     end
-   end
-
-   class CodesysDB < DB #----------------------------------------------------------------------
-     include Singleton
-     def initialize()
-       super
-       @glob, @pre, @post = "#{DB_DIR}/*/system-char-id", "#{DB_DIR}/", "/system-char-id"
-       open_dbs()
-     end
-     #def keys() @dbs.keys.sort end #どんなCodesysの情報を持っているかの一覧
-     def keys() @dbs.keys end #どんなCodesysの情報を持っているかの一覧
-     def get_codesys(t)
-       db = get(t)
-       return nil unless db
-       return Codesys.new(t)
-     end
-   end
-
-   class Codesys < DB #======================================================================
-     def initialize(name)
-#       super
-       @name = name
-       @dbs = CodesysDB.instance
-     end
-     def keys() #どんなコードポイントの情報を持っているかの一覧
-       ks = @dbs.get(@name).keys
-       if @name =~ /jisx0208/ #特別処理
-        n = @dbs.get('=jis-x0208').keys 
-        #       p ['keys', @name, ks, n]
-        ks += n
-       end
-       ks.map! {|k| to_num(k) }
-       ks
-     end
-     def get(key)
-       v = @dbs.get(@name, key)
-       return v if v
-       if @name =~ /jisx0208/ #jisx0208が含まれている場合だけ特別処理する
-        return @dbs.get('=jis-x0208', key)
-       end
-       return nil
-     end
-     def each()
-       return unless block_given?
-       db = @dbs.get(@name)
-       return nil unless db
-       db.each {|k, v|
-        k = to_num(k)
-        v = to_num(v)
-        k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
-        vv = @dbs.get(@name, k)        #p ['each', t, k, v, vv]
-        yield(k, vv)
-       }
-     end
-     def each_sort()
-       return unless block_given?
-       db = @dbs.get(@name)
-       return nil unless db
-       ar = db.to_a
-       ar.map! {|k, v| [to_num(k), to_num(v)] }
-       ar.sort.each {|k, v|
-        k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
-        vv = @dbs.get(@name, k)        #p ['each', t, k, v, vv]
-        yield(k, vv)
-       }
-     end
-   end
+       u = get_char_attribute(a)
+       return u if u != nil
+      }
+      return nil
+    end
+
+    #----------------------------------------------------------------------CCS関係
+    def to_utf8() Uconv.u4tou8(Character.u4itou4(ucs())) end #UTF8文字列を返す
+    #alias to_s to_utf8
+    alias to_s mcs_utf8
+    def map_utf8()
+      u = ucs()
+      if u.nil? || 0xffff < u
+       return to_er()
+      else
+       return to_utf8()
+      end
+    end
+    alias map_ucs map_utf8
+    def map_ucs_er()
+      u = ucs()
+      if u.nil? || 0xffff < u
+       return to_er()
+      else
+       return Character.get(u).to_er()
+      end
+    end
+    def to_euc()
+      u = ucs()
+      return "" if u.nil? || 0xffff < u
+      Uconv.u16toeuc(Uconv.u4tou16(Character.u4itou4(ucs())))
+    end
+    def map_euc()
+      e = to_euc()
+      return e if e != ""
+      return to_er()
+    end
+    def to_sjis()
+      u = ucs()
+      return "" if u.nil? || 0xffff < u
+      Uconv.u16tosjis(Uconv.u4tou16(Character.u4itou4(ucs())))
+    end
+    def map_sjis()
+      e = to_sjis()
+      return e if e != ""
+      return to_er()
+    end
+
+    #----------------------------------------------------------------------
+    def to_er(codesys=nil) #実体参照を返す、希望するcodesysが引数(未実装)
+      return "" if @char_id == nil
+      return sprintf("&#x%04x;", @char_id) if @char_id <= 0xffff
+      return sprintf("&#x%05x;", @char_id) if @char_id <= 0xfffff
+      EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
+       code = self[codesys]
+       next if code == nil
+       return sprintf("&#{er_prefix}%0#{keta}#{numtype};", code)
+      }
+      return sprintf("&MCS-%08X;", @char_id) #本当はこれは無しにしたい
+    end
+    def to_er_list()
+      ar = []
+      EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
+       er = to_er(codesys)
+       ar << er if er != nil
+      }
+      ar
+    end
+
+    def inspect_x()
+      return "<>" if @char_id == nil
+      ar = [to_utf8(), to_er().sub(/^&/,'').chop]
+      "<"+ar.join(',')+">"
+    end
+    alias inspect inspect_x
+    def inspect_all_codesys() #未完成
+      #to_erを全てのcodesysにおいて実行する。その結果をコンパクトにまとめる
+    end
+    def inspect_all()
+      ar = [inspect.chop]
+      alist.to_a.sort.each {|a, v| ar << "#{a}:#{v}" }
+      return ar.join(',')+">"
+    end
+    def get_attributes()
+      str = ""
+      alist.to_a.sort.each {|a, v|
+       str += "#{a}: #{v}\n"
+      }
+      str
+    end
+
+    def inspect_ids(hex_flag=false)
+      ids = decompose
+      ar = []
+      ar << (hex_flag ? "x"+mcs_hex : to_utf8)
+      if to_s != ids #idsが部品そのものだったら部品追加はしない
+       ids.each_char {|ch|
+         char = ch.char
+         next if char.is_ids?
+         if hex_flag then
+           ar << "x"+char.mcs_hex
+         else
+           u = char.to_utf8
+           if u != ""
+             ar << u
+           else
+             ar << char.to_er
+           end
+         end
+       }
+      end
+      return "("+ar.join("\t")+")"
+    end
+
+    #----------------------------------------------------------------------IDS関係
+    def decompose
+      k = self.to_s
+      #       idss = self['ids']
+      #       return idss if idss
+      #       return k if self.is_basic_kanji? #基本漢字はstop kanjiとするぞと。
+      return self['ids-represent'] if self['ids-represent'] #ids_representを持っている場合はその値とする。
+      return self['ids-element'] if self['ids-element'] #ids_elementを持っている場合はその値とする。
+
+      idss = self['ids-meaning']
+      return idss if idss != nil && 0 < idss.length && k != idss
+      idss = self['ids-aggregated']
+      return idss if idss != nil && 0 < idss.length && k != idss
+      idss = self['ids']
+      return idss if idss != nil && 0 < idss.length && k != idss
+      return k
+      #       return k if idss.nil? || idss.length == 0 || k == idss
+      #       if idss.char_length == 2
+      #        p ['What???', k, idss, k.inspect_all]
+      #         #return idssx[1] #二個目だけ返すとか?
+      #         return k #IDSに展開する方法が無いと。
+      #       end
+      #       return k if k == idss
+      #       if idss.include?(k) #<C5-4C4D><C6-4A37>この二文字のBUG対策
+      #         #return idss.sub(k, '')
+      #         return k #IDSに展開する方法が無いと。
+      #       end
+      #       return idss
+    end
+    def decompose_all
+      pde = ""
+      de = self.decompose #出発点
+      level = 0
+      while true
+       pde = de
+       de = pde.decompose #もう一度分解をしてみる。
+       break if pde == de #ループを抜けだす
+       exit if 10 < level #p ['too many recursive', self] 
+       level += 1
+      end
+      return de
+    end
+    def decompose_all_nu(level=nil)
+      level = 0 if level.nil?
+      if 10 < level
+       p ['too many recursive', self] 
+       exit
+      end
+      de = self.decompose
+      return de.decompose_all(level+1) if de != self #なにか変化があったから再帰
+      return de #もうこれ以上変化は無さそうだぞと。
+    end
+    def is_ids?() 0x2ff0 <= @char_id && @char_id <= 0x2fff end
+    def ids_operator_argc()
+      return 0 unless is_ids?
+      return 3 if @char_id == 0x2ff2 || @char_id == 0x2ff3
+      return 2
+    end
+  end
+
+  class DBS #======================================================================複数のDBを集めたclass、未完成
+  end
+
+  class ADB < BDB::Hash #======================================================================一つのDB
+    def initialize(*args)
+      super
+      @modified = false
+      at_exit {
+       if @modified
+         self.close #これがないと、うまくデータベースがセーブされないのです。
+       end
+      }
+    end
+    def self.open_create(filename)
+      ADB.open(filename, nil, BDB::CREATE | BDB::EXCL) #上書きはしない
+    end
+    def mykey(key)
+      if key.is_a?(String)
+       if key.char_length == 1
+         return '?'+key  #Stringだったら引く前に?を足す
+       end
+      end
+      #key = key.to_s if key.is_a?(Numeric) #NumberだったらStringにする。
+      #ここで && key ! =~ /^\?/ をいれると、?自身を検索できなくなってしまう。
+      return key
+    end
+    def myvalue(v)
+      return v if v == nil
+      return v.to_i if v =~ /^\d+$/ #数字だったらここで変換しておく
+      return v.sub(/^\?/, '') if v =~ /^\?/ #冒頭の?は取り除く
+      return $1 if v =~ /^"(.+)"$/ #最初と最後に"がついていたら、取り除く
+      #p ['get', v, t, key, db]
+      #return parse_sexp(v) if v =~ /^\(.+\)$/ #最初と最後が()の時は、S式にparseする
+      return v #それ以外って何?
+    end
+    def myget(key) #keyキーを引いて返す
+      key = mykey(key)
+      v = get(key) #存在しなかったらnilを返すことになる
+      return myvalue(v)
+    end
+    def myput(key, v) #keyにvをいれる
+      key = mykey(key)
+      put(key, v) #putする
+      @modified = true
+    end
+  end
+
+  class DB #======================================================= データベース群のabstract class
+    def self.unix_to_win(unix) #Windowsファイル名制限のため、変換する
+      win = unix.gsub(/</, '(')
+      win.gsub!(/>/, ')')
+      win.gsub!(/\*/, '+')
+      win.gsub!(/\?/, '!')
+      return win
+    end
+    def self.win_to_unix(win)
+      unix = win.gsub(%r|\)|, '>')
+      unix.gsub!(%r|\(|, '<')
+      unix.gsub!(%r|!|, '?')
+      unix.gsub!(%r|\+|, '*')
+      return unix
+    end
+    def get_filename(t)
+      return @pre + DB.unix_to_win(t) + @post if windows?
+      return @pre + t + @post
+    end
+    def get_dirname(t) File.dirname(get_filename(t)) end
+    def open_dbs()
+      @dbs = Hash.new
+      keys = find_keys()
+      keys.each {|key| open_db(key) }
+    end
+    def find_keys()
+      files = []
+      Dir.glob(@glob){|f|
+       next if ! File.file?(f)
+       next if f =~ /.txt$/
+       files << f
+      }
+      keys = []
+      files.each {|f|
+       t = DB.win_to_unix(f)
+       t.sub!(%r|^#{@pre}|, '')
+       t.sub!(%r|#{@post}$|, '') if @post != ""
+       keys << t
+      }
+      return keys
+    end
+    def close_db(t)
+      db = get(t)
+      return nil if db.nil?
+      db.close
+      @dbs.delete(t)
+    end
+    def open_db(t)
+      return nil if get(t) #すでにopenしていたら再openはしない。
+      begin
+       bdb = ADB.open(get_filename(t), nil, 0)
+       @dbs[t] = bdb if bdb != nil
+      rescue
+       p ["open error", get_filename(t)]; return nil
+      end
+      return true
+    end
+    def make_db(t, h=nil) #tという名前でhという中身のデータベースを作る
+      return nil if get(t) #すでにある場合はreturn
+      Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
+      db = nil
+      begin
+       db = ADB.open_create(get_filename(t)) #上書きはしない
+       if h != nil
+         h.each {|k, v|
+           k = '?'+k if k.is_a?(String)
+           db[k] = v
+         }
+       end
+       db.close
+      rescue
+       p ["make error", get_filename(t)]; return nil
+      end
+      return true
+    end
+    def make_db_no_question_mark(t, h=nil) #tという名前でhという中身のデータベースを作る
+      return nil if get(t) #すでにある場合はreturn
+      Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
+      db = nil
+      begin
+       db = ADB.open_create(get_filename(t)) #上書きはしない
+       if h != nil
+         h.each {|k, v|
+           #        k = '?'+k if k.is_a?(String)
+           db[k] = v
+         }
+       end
+       db.close
+      rescue
+       p ["make error", get_filename(t)]; return nil
+      end
+      return true
+    end
+    def remove_db(t) #tという名前のデータベースを消去する
+      db = get(t)
+      if db
+       db.close
+       @dbs.delete(t)
+      end
+      begin
+       File.unlink(get_filename(t)) if FileTest.file?(get_filename(t))
+      rescue
+       p ["unlink error", get_filename(t)]; return nil
+      end
+      dn = get_dirname(t)
+      Dir.rmdir(dn) if FileTest.directory?(dn) && Dir.entries(dn).length <= 2 #空directoryだったら消す
+      return true
+    end
+    def to_num(s)
+      return s.to_i if s =~ /^\d+$/
+      return s
+    end
+    def dump_db(t)
+      db = get(t)
+      return nil unless db
+      file = get_filename(t)
+      open("#{file}.txt", "w"){|out|
+       #        out.binmode.sync = true
+       ar = db.to_a
+       ar.map! {|k, v| [to_num(k), to_num(v)] }
+       ar.sort.each {|k, v|
+         out.printf("%s\t%s\n", k, v)
+       }
+      }
+      return true
+    end
+    def each_db()  @dbs.to_a.sort.each {|t, db| yield(t, db) } end
+    def dump_all()  each_db {|t, db| dump_db(t) } end
+    def close_all() each_db {|t, db| db.close   } end
+    def keys() @dbs.keys end
+    def each(t)
+      return unless block_given?
+      db = @dbs[t]
+      return nil unless db
+      db.each {|k, v|
+       k = to_num(k)
+       v = to_num(v)
+       k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+       vv = get(t, k)  #p ['each', t, k, v, vv]
+       yield(k, vv)
+      }
+    end
+    def each_sort(t)
+      return unless block_given?
+      db = @dbs[t]
+      return nil unless db
+      ar = db.to_a
+      ar.map! {|k, v| [to_num(k), to_num(v)] }
+      ar.sort.each {|k, v|
+       k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+       vv = get(t, k)  #p ['each', t, k, v, vv]
+       yield(k, vv)
+      }
+    end
+    #----------------------------------------------------------------------
+    def get(t, key=nil) #tというデータベースのkeyキーを引いて返す
+      db = @dbs[t]
+      return db if key.nil?
+      return nil unless db
+      return db.myget(key)
+    end
+    def put(t, key, v) #tというデータベースのkeyにvをいれる
+      db = @dbs[t]
+      if db == nil
+       db = make_db(t) 
+       db = open_db(t) 
+       db = @dbs[t]
+      end
+      db.myput(key, v) #putする
+    end
+  end
+
+  class CharDB < DB #------------------------------------ MCS-UTF8をキーとした属性へのデータベース
+    include Singleton
+    def initialize()
+      super
+      @glob, @pre, @post = "#{DB_DIR}/system-char-id/*", "#{DB_DIR}/system-char-id/", ""
+      open_dbs()
+    end
+    def get_all(u8) #全データベースのu8キーを引いてHashにまとめて返す
+      atrs = Hash.new
+      @dbs.each {|t, db|
+       v = get(t, u8)
+       atrs[t] = v if v != nil
+      }
+      return atrs
+    end
+  end
+
+  class CodesysDB < DB #----------------------------------------------------------------------
+    include Singleton
+    def initialize()
+      super
+      @glob, @pre, @post = "#{DB_DIR}/*/system-char-id", "#{DB_DIR}/", "/system-char-id"
+      open_dbs()
+    end
+    #def keys() @dbs.keys.sort end #どんなCodesysの情報を持っているかの一覧
+    def keys() @dbs.keys end #どんなCodesysの情報を持っているかの一覧
+    def get_codesys(t)
+      db = get(t)
+      return nil unless db
+      return Codesys.new(t)
+    end
+  end
+
+  class Codesys < DB #======================================================================
+    def initialize(name)
+      #       super
+      @name = name
+      @dbs = CodesysDB.instance
+    end
+    def keys() #どんなコードポイントの情報を持っているかの一覧
+      ks = @dbs.get(@name).keys
+      if @name =~ /jisx0208/ #特別処理
+       n = @dbs.get('=jis-x0208').keys 
+       #        p ['keys', @name, ks, n]
+       ks += n
+      end
+      ks.map! {|k| to_num(k) }
+      ks
+    end
+    def get(key)
+      v = @dbs.get(@name, key)
+      return v if v
+      if @name =~ /jisx0208/ #jisx0208が含まれている場合だけ特別処理する
+       return @dbs.get('=jis-x0208', key)
+      end
+      return nil
+    end
+    def each()
+      return unless block_given?
+      db = @dbs.get(@name)
+      return nil unless db
+      db.each {|k, v|
+       k = to_num(k)
+       v = to_num(v)
+       k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+       vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
+       yield(k, vv)
+      }
+    end
+    def each_sort()
+      return unless block_given?
+      db = @dbs.get(@name)
+      return nil unless db
+      ar = db.to_a
+      ar.map! {|k, v| [to_num(k), to_num(v)] }
+      ar.sort.each {|k, v|
+       k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+       vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
+       yield(k, vv)
+      }
+    end
+  end
+
+  class JISX0208
+    def initialize
+      db = CodesysDB.instance
+      @common = db.get_codesys('=jis-x0208')
+      @newest = db.get_codesys('japanese-jisx0208-1990')
+    end
+    def get_char(code)
+      char = @common.get(code)
+      return char unless char.nil?
+      char = @newest.get(code)
+      return char unless char.nil?
+      return nil
+    end
+  end
 
   class IDS_TEXT_DB < DB #======================================================================
     include Singleton
@@ -943,7 +958,7 @@ IDS-CBETA.txt
        dir = File.dirname(file) + '/../ids-error'
        Dir.mkdir(dir) unless FileTest.exist?(dir)
        errfile = dir + '/' + File.basename(file)
-#      p [file, errfile]
+       #       p [file, errfile]
        open(errfile, "w"){|out|
          out.binmode.sync = true
          each_line(file){|code, ch, ids|
@@ -1012,7 +1027,7 @@ IDS-CBETA.txt
              @same_ids_counter += 1
            else #しかしいままでのIDSと新しいIDSが食い違った場合は?
              @conflict_ids_counter += 1
-#            print "conflict   #{char.inspect} #{code} #{ids}  #{char['ids']}\n"
+             #       print "conflict   #{char.inspect} #{code} #{ids}  #{char['ids']}\n"
            end
          end
        }
@@ -1059,7 +1074,7 @@ IDS-CBETA.txt
          ar.each {|ch|
            char = ch.char
            v = char[codesys]
-#          p [codesys, v] if v
+           #       p [codesys, v] if v
            if v #EntityReferenceの順番に準拠する。
              ar2 << ch
              ar.delete(ch)
@@ -1068,12 +1083,12 @@ IDS-CBETA.txt
        }
       end
       if 0 < ar.length
-#      p ['yokuwakaran character', ar, ar[0].inspect_all, arorg]
+       #       p ['yokuwakaran character', ar, ar[0].inspect_all, arorg]
        EntityReference.each_codesys{|codesys, er_prefix, keta, numtype|
          ar.dup.each {|ch|
            char = ch.char
            v = char[codesys]
-#          p [codesys, v] if v
+           #       p [codesys, v] if v
          }
        }
       end
@@ -1134,10 +1149,10 @@ IDS-CBETA.txt
        }
        ar.sort!
        ar.uniq!
-#やっぱりIDS文字も加えることにする. by eto 2003-02-05
-#      ar.delete_if {|ch|
-#        ch.char.is_ids? #IDS文字はまぎれこませない。
-#      }
+       #やっぱりIDS文字も加えることにする. by eto 2003-02-05
+       #       ar.delete_if {|ch|
+       #         ch.char.is_ids? #IDS文字はまぎれこませない。
+       #       }
        str = ar.join('')
        char['ids-parts'] = str
       }
@@ -1149,12 +1164,12 @@ IDS-CBETA.txt
        char = k.char
        parts = char.ids_parts
        parts.each_char {|ch|
-#        part = ch.char
+         #       part = ch.char
          h[ch] = [] if h[ch].nil?
          h[ch] << k
-#        h[ch] += k
-#        part['ids-contained'] = "" if part['ids-contained'].nil?
-#        part['ids-contained'] += k
+         #       h[ch] += k
+         #       part['ids-contained'] = "" if part['ids-contained'].nil?
+         #       part['ids-contained'] += k
        }
       }
       h.each {|k, v|
@@ -1186,7 +1201,7 @@ IDS-CBETA.txt
     end
     attr_reader :nodenum
     alias original_add <<
-    private :original_add
+      private :original_add
     def <<(obj)
       original_add(obj)
       @nodenum -= 1 if @nodenum
@@ -1378,7 +1393,7 @@ iso-10646-comment
     end
     def move_to_obsolete(file)
       cmd = "mv #{file} #{@odir}"
-#      p cmd
+      #      p cmd
       system cmd
     end
   end
@@ -1388,7 +1403,7 @@ iso-10646-comment
     #JP_JOYO_FILE = DB_DIR+"/../jp-joyo.txt" #EUC-jisx0213
     JP_JOYO_FILE = DB_DIR+"/../joyo-ucs.txt" #UCS
     COMPOSIT_KANJI = "鳴名加品古知問間聞取兄見切分粉貧林森校東明住位好岩砂里男畑習休短空坂島倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守灰秋秒困国医包同合舌居右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣"
-#    COMPOSIT_KANJI = "鳴名加品古"
+    #    COMPOSIT_KANJI = "鳴名加品古"
     def initialize
       @nchars = []
       read_file