# prototype.rb
# $Id: prototype.rb,v 1.5 2000/11/18 18:48:40 keiko Exp $
require "util"
require "variable"
class Prototype
INDENT = " "*4
def indent(n=1)
INDENT*n
end
def initialize(type_or_module, name, args, rtn)
@vtype = (type_or_module == :module ? nil : type_or_module)
@name = name
@args = args
@rtnval = rtn
@lenvar = []
@rtnlenvar =[]
# check output array size
chk = @rtnval.find_all{|o| o.ary}
chk += @args.find_all{|o| (o.ary && !o.output?)}
chk.each{|o|
size = []
o.ary.split(",").each do |i|
case i
when "*"
size.push "DFLT_SIZE"
next
when /^\d+$/
size.push i
next
when /^(\d+):(\d+)$/
size.push($2.to_i - $1.to_i + 1)
next
end
wk = i.gsub(/[a-z]+[a-z0-9]*/){|j|
sz = @args.find{|x| x.name == j}
if sz
sz.localvariable[1]
else
"DFLT_SIZE"
end
}
case wk
when /(.+):(.+)/
ed = ($2 == "*" ? "DFLT_SIZE" : $2)
size.push( "(" + (ed + "-" + $1 + "+1").
gsub("--", "+").gsub("-0","").
gsub("[-]1[+]1", "").gsub("[+]1[+]1", "+2") +
")" )
else
size.push wk
end
end
o.setarysize(size)
p ["Prototype:1", @name, o.ary, size, o.arysize] if $DEBUG
}
# set @lenvar
@args.each{|i|
j = i.ftnlen
@lenvar.push j if j
}
# set @rtnlenvar
if @vtype
@rtnval.each{|i|
j = i.ftnlen
@rtnlenvar.push j if j
}
end
end
def to_s
buf = head
defvar = defvar()
buf << defvar
buf << initialization
buf << call
buf << result
buf << tail
end
def head
vstr = @args.find_all{|i| i.input?}.
collect{|i| i.name}.unshift("obj").join(", ")
buf = "static VALUE\n"
buf << format("dcl_%s(%s)\n", @name, vstr)
buf << format("%sVALUE %s;\n{\n", indent, vstr)
end
def defvar
buf = ""
vars = @args + (@vtype ? @rtnval : [])
vars.each{|i|
t, n = i.localvariable
if /\*$/ =~ t
buf << format("%s%s%s;\n", indent, t, n)
else
buf << format("%s%s %s;\n", indent, t, n)
end
}
@rtnval.each{|i|
buf << format("%s%s %s;\n", indent, "VALUE", i.name) if !i.input?
}
buf << "\n" unless buf.empty?
buf
end
def initialization
buf = ""
@args.find_all{|i| i.input?}.each{|i|
j = i.checktype
buf << j.gsub(/^/, indent) if j
}
buf << "\n" unless buf.empty?
@args.find_all{|i| i.input? && !i.ary}.each{|i|
j = i.initialization
buf << j.gsub(/^/, indent) if j
}
@args.find_all{|i| i.input? && i.ary}.each{|i|
j = i.initialization
buf << j.gsub(/^/, indent) if j
}
buf << "\n" unless buf.empty?
wk = @rtnval.find_all{|i| !i.input?} +
@args.find_all{|i| i.work?}
wk.each{|i|
j = i.allocworkingarea
buf << j.gsub(/^/, indent) if j
}
buf << "\n" unless buf.empty?
buf
end
def call
buf = ""
buf << indent
if @vtype
if ( @vtype =~ /CHARACTER|COMPLEX/)
wk = [@rtnval[0].arg_name] + @rtnlenvar +
@args.collect{|i| i.arg_name} + @lenvar
else
buf << (@rtnval[0].prefix + @rtnval[0].name + " = ")
wk = @args.collect{|i| i.arg_name} + @lenvar
end
else
wk = @args.collect{|i| i.arg_name} + @lenvar
end
buf << format("%s_(%s);\n", @name, wk.join(", "))
buf << "\n" unless buf.empty?
buf
end
def result
buf = ""
if @vtype
buf << indent + @rtnval[0].getresult
else
@rtnval.each{|i|
buf << (indent + i.getresult)
}
end
buf << "\n" unless buf.empty?
# free area allocated at initialization
@args.find_all{|i| i.input?}.each{|i|
j = i.freecary
buf << j.gsub(/^/, indent) if j
}
# free area allocated at allocworkingarea
wk = @rtnval.find_all{|i| !i.input?} +
@args.find_all{|i| i.work?}
wk.each{|i|
j = i.freeworkingarea
buf << j.gsub(/^/, indent) if j
}
buf << "\n" unless buf.empty?
if (@vtype || (@rtnval.size == 1))
buf << indent +
format("return %s;\n", @rtnval[0].name)
elsif ( @rtnval.size == 0 )
buf << indent + "return Qnil;\n"
else
vars = @rtnval.collect{|i| i.name}
buf << indent +
format("return rb_ary_new3(%d, %s);\n",
vars.size, vars.join(", "))
end
buf << "\n" unless buf.empty?
buf
end
def tail
"}\n"
end
end
syntax highlighted by Code2HTML, v. 0.9.1