# 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