#!/usr/local/bin/ruby # $Id: erb.rb,v 1.29 1999/05/19 17:11:30 mas Exp $ # $Author: mas $ # Copyright (c) 1999 Masatoshi SEKI require 'enumre.rb' # http://www2a.biglobe.ne.jp/%7Eseki/ruby/enumre.rb require 'strio.rb' # http://www2a.biglobe.ne.jp/%7Eseki/ruby/strio.rb class ERb Revision = '$Date: 1999/05/19 17:11:30 $' def version "erb.rb [#{ERb::Revision.split[1]}]" end module_function :version def pre_compile(s) list = [] s.each_line do |line| line.gsub!(/(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)/) do |m| "\n#{m}\n" end list += line.split("\n") list.push("\n") end escape = @escape.cp list = escape.gsub(list) { case escape.matching_data[0].join when '<%%' ['<', '%'] when '%%>' ['%', '>'] end } end module_function :pre_compile private :pre_compile def compile(s) cmdlist = [] str_table = [] list = pre_compile(s) head = @head.cp list = head.sub(list) { match = head.matching_data match[1].join.each do |line| cmdlist.push("print #{line.dump}") end nil } compile = @compile.cp list = compile.gsub(list) { match = compile.matching_data content = match[1].join case match[0].join when '<%' cmdlist.push(content) when '<%=' cmdlist.push("print (#{content})") when '<%#' =begin for ruby 1.3 ... cmdlist.push('=begin') cmdlist.push(content) cmdlist.push('=end') =end cmdlist.push("# #{content.dump}") end match[3].join.each do |line| cmdlist.push("print #{line.dump}") end nil } list.join.each do |line| cmdlist.push("print #{line.dump}") end cmdlist.join("\n") end module_function :compile private :compile def setup_compiler first = ARegexpFirst.new stag = ARegexpInclude.new(['<%=', '<%#', '<%']) notstag = stag.dup.negate.repeat(0, nil).greedy(true) etag = ARegexpEq.new('%>') any = ARegexpAny.new.repeat(0, nil).greedy(false) @head = ARegexp.new([first, notstag]); @compile = ARegexp.new([stag, any, etag, notstag]) escape = ARegexpInclude.new(['<%%', '%%>']) @escape = ARegexp.new([escape]) end module_function :setup_compiler private :setup_compiler def initialize(str, safe_level=nil) @src = ERb.compile(str) @safe_level = safe_level end attr :src setup_compiler def run(b=TOPLEVEL_BINDING) if @safe_level print self.result(b) else eval(@src, b) end end def result(b=TOPLEVEL_BINDING) if @safe_level StringIO.as_stdout(@safe_level) { eval(@src, b) } else StringIO.as_stdout { eval(@src, b) } end end end if __FILE__ == $0 def ARGV.switch return nil if self.empty? arg = self.shift return nil if arg == '--' if arg =~ /^-(.)(.*)/ return arg if $1 == '-' raise 'unknown switch "-"' if $2.index('-') self.unshift "-#{$2}" if $2.size > 0 "-#{$1}" else self.unshift arg nil end end def ARGV.req_arg self.shift || raise('missing argument') end begin while switch = ARGV.switch case switch when '-x' # ruby source output = true when '-n' # line number number = true when '-v' # verbose $VERBOSE = true when '--version' # version STDERR.puts ERb.version exit when '-d', '--debug' # debug $DEBUG = true when '-r' # require require ARGV.req_arg when '-S' # sacurity level arg = ARGV.req_arg raise "invalid security level #{arg.dump}" unless arg =~ /^[0-4]$/ safe_level = arg.to_i else raise "unknown switch #{switch.dump}" end end rescue # usage STDERR.puts $!.to_s STDERR.puts File.basename($0) + " -x -n -v -d -r module -S [0-4] [--] [file]" exit 1 end src = $<.read exit 2 unless src erb = ERb.new(src, safe_level) if output if number l = 1 for line in erb.src puts "%3d %s"%[l, line] l += 1 end else puts erb.src end else erb.run end end