1 class Preprocessor
 2   def initialize(input, output, filename)
 3     @input = input
 4     @output = output
 5     @filename = filename
 6     @linenum = 1
 7   end
 8 
 9   def getline
10     line = @input.gets
11     @linenum += 1 if not line.nil?
12     return line
13   end
14 
15   def preprocess
16     success = false
17     begin
18       loop do
19         line = getline
20         break if line.nil?
21         case line
22         when /(.*[^\\]|^)\#\{(.*?)\}(.*)/
23           puts "#{$1}#{evaluate($2, @linenum)}#{$3}"
24         when /^\#ruby\s+<<(.*)/
25           marker = $1
26           str = ''
27           evalstart = @linenum
28           loop do
29             line = getline
30             if line.nil? then
31               raise "End of input without #{marker}"
32             end
33             break if line.chomp == marker
34             str << line
35           end
36           result = evaluate(str, evalstart)
37           puts result if not result.nil?
38         when /^\#ruby\s+(.*)/
39           str = line = $1
40           while line[-1] == ?\\
41             str.chop!
42             line = getline
43             break if line.nil?
44             line.chomp!
45             str << line
46           end
47           result = evaluate(str, @linenum)
48           puts result if not result.nil?
49         else
50           puts line
51         end
52       end
53       success = true
54     ensure
55       if not success then
56         $stderr.puts "Error on line #{@linenum}:"
57       end
58     end
59   end
60 
61   def evaluate(str, linenum)
62     result = eval(str, TOPLEVEL_BINDING, @filename, linenum)
63     success = true
64     return result
65   end
66 
67   def puts(line)
68     @output.puts(line)
69   end
70 end
71 
72 def puts(line)
73   $preprocessor.puts(line)
74 end
75 
76 if __FILE__ == $0 then
77   input_file = ARGV[0]
78   output_file = ARGV[1]
79 
80   input = input_file ? File.open(input_file) : $stdin
81   output = output_file ? File.open(output_file, 'w') : $stdout
82 
83   success = false
84   begin
85     $preprocessor = Preprocessor.new(input, output, input_file || "(stdin)")
86     $preprocessor.preprocess()
87     success = true
88   ensure
89     if not success then
90       File.unlink(output_file) rescue Errno::ENOENT
91     end
92   end
93 end