--- code ---
#!/home/ummaycoc/bin/ruby -w

# Number stuff down the side
# REM means remark (NO number)
# No number means continue last number
# \ is same as no number...
# -d debug mode.

class NRuby
  def initialize(debug = false)
    @line  = 0
    @next  = nil
    @debug = debug
  end

  def goto(line)
    @next = line
  end

  def stop()
    @next = nil
  end

  def NRuby.error(msg)
    $stderr.puts("NRubyErr:  #{msg}")
    exit(-1)
  end

  def debug(code, line)
    if @debug then
      puts "NO CODE #{line}"			unless code[line]
      puts "**#{line}**\n#{code[line]}\n"	if code[line]
    end
  end


  def NRuby.read(input, start)
    code, prev	= Hash.new(false), start
    input.each {|line|
      doPrev	= false
      case line
        when /^\s*REM(\s+|(\s*$))/i	then ;
        when /^\s*$/			then ;
        when /^\s*(\d+)\s+(.*)$/	then prev		= $1.to_i
        				     code[prev]		= [$2]
        when /^\s*\\\s+(.*)$/		then doPrev, line	= true, $1
        else				     doPrev		= true
      end
      error "No Previous Line!"		if prev.nil? && doPrev
      code[prev] = []                   unless code.include? prev
      code[prev] << line		if doPrev
    }

    code.each_key {|key|
      code[key] = code[key].join(" \n")
    }

    code
  end

  def execute(code)
    lastline = code.keys.max
    until @line.nil? || @line > lastline
      debug(code, @line)
      @next = nil
      eval(code[@line]) if code[@line]
      @line = @next || @line + 1
    end
  end
end


debug = false
if ARGV.length > 0 then
  if ARGV.include? "-d" then
    debug = true
    ARGV.delete "-d"
  end
end

@___nruby___, start = NRuby.new(debug), nil

if ARGV.length > 0 then
  stdin_read, lines = false, nil
  until ARGV.empty? do
    arg = ARGV.shift
    case arg
      when /^-+h/i
        $stderr.puts <<-END_HELP
  #{File.basename($0)} [-z|-s num] [-d] [files+]
    -z sets the first number label to zero - for unlabeled code at
beginning of program.
    -s num sets the first number label to num.  Same use as -z.
    -d debug mode.
    files list what files to read from.  - is stdin.

    If no inputs are given, a program is read from stdin and executed.
  END_HELP
        exit(-1)
      when '-'
        NRuby.error "Already read from stdin." if stdin_read
        stdin_read = true
        lines = $stdin.readlines
      when '-z'
        start = 0
      when '-s'
        NRuby.error "No argument given with -s." if ARGV.empty?
        start = ARGV.shift
        NRuby.error "Argument to -s must be integer." unless start =~ /-?\d+$/
        start = start.to_i
      else
        NRuby.error "#{arg} doesn't exist..."  unless FileTest.exists?(arg)
        NRuby.error "#{arg} isn't a file..."   unless FileTest.file?(arg)
        NRuby.error "#{arg} isn't readable..." unless FileTest.readable?(arg)
        lines = File.readlines(arg)
    end

    lines ||= $stdin.readlines
    lines.each {|l| l.chomp!}
    @___nruby___.execute(NRuby.read(lines, start))
  end
else
  lines = $stdin.readlines.map {|l| l.chomp}
  if lines.nil? || lines.empty? then
    NRuby.error "No input given."
  else
    @___nruby___.execute(NRuby.read(lines, start))
  end
end


--- a usage ---
[ummaycoc@queen ummaycoc]$ echo '
10 x = 1
11 x += 1
12 puts x
15 goto 18 if x == 10
16 goto 11
18 puts "done"
stop' | nruby
2
3
4
5
6
7
8
9
10
done
[ummaycoc@queen ummaycoc]$

--- usage 2 & 3 ---

[ummaycoc@queen bin]$ echo 'puts "hi"' | nruby
NRubyErr:  No Previous Line!
[ummaycoc@queen bin]$ echo 'puts "hi"' | nruby -z
hi
[ummaycoc@queen bin]$

-------------------------------

-- 
There's no word in the English language for what you do to a dead
thing to make it stop chasing you.