[ruby-talk:00356] magic parser

From: gotoken@... (GOTO Kentaro)
Date: 1999-05-28 13:18:07 UTC
List: ruby-talk #356
Hi,

I wrote a unix magic(5) parser. Would you complete a file(1) command?

thanks

-- gotoken


#
# class MagicFile
#
#   MagicFile is a class as magic(5) parser. 
#
# class methods
#
#   new([filname])
#
#     Reads filename and return MagicFile object. A MagicFile object can be
#     treat as an array, which consists of arrays. Each member of MagicFile 
#     consists of five members -- offset, type, test, message and more test. 
#     Each of offset, type, test and message is a string. The more test is
#     an array which is structured as same as MagicFile.  If filename is 
#     omitted /etc/magic would be read. 
#

class MagicFile
  TraditionalMagicFile = "/etc/magic"

  def initialize(file = TraditionalMagicFile)
    if file.kind_of?(String)
      @file = open(File.expand_path(file)).read.split("\n").
	delete_if{|i| i =~ /^\s*(#.*)?$/} # delete comment or null line
    else
      raise ArgumentError.new("filename")
    end
    @magic = []

    pat = /^(>*)(.*)/
    shellword = /(?:[^\\\s]|\\.)+/
    level = 0
    stack = []

    @file.each_with_index do |line,nr|
      os, type, data, *msg = line.scan(shellword)
      message = msg.join(' ')
      lv, offset = os.scan(pat)[0]
      lv = lv.size

      cur = [offset, type, data, message, []]

      if lv == 0
	@magic.push(stack[0]) unless nr == 0  # push!!
	stack = [cur]
      elsif lv <= level + 1  # 0 < lv
	(level-lv+1).times{ stack.pop }
	stack[-1][-1].push cur
	stack.push cur
      else
	raise "`>' nest illegal"
      end

      level = lv
    end

    @magic.push(stack[0]) # push!!
  end
  
  def method_missing(mid, *arg, &blk)
    @magic.__send__(mid, *arg, &blk)
  end

  def a2s(ary, lv)
    if ary[4].empty?
      ">"*lv + ary[0..3].join("\t")
    else
      ">"*lv + ary[0..3].join("\t") + "\n" + 
	ary[4].filter{|i| a2s(i, lv+1)}.join("\n")
    end
  end

  def to_s
    @magic.collect{|i| a2s(i,0)}.join("\n")
  end
  private :a2s
end

if __FILE__ == $0
  magic = MagicFile.new
  print magic, "\n"
end

In This Thread

Prev Next