print.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
---------------------------> Sather 1.1 source file <--------------------------
-- Copyright (C) International Computer Science Institute, 1995. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to sather-bugs@icsi.berkeley.edu. <----------
class ATTRSORT < $IS_LT{ATTRSORT}
class ATTRSORT < $IS_LT{ATTRSORT} is
include COMPARABLE;
attr name:STR;
attr elt:ELT;
create(n:STR,e:ELT):ATTRSORT is
r::=new;
r.name:=n;-- ATTRSORT::name
r.elt:=e;-- ATTRSORT::elt
return r;
end;
is_lt(b:SAME):BOOL is return name.is_lt(b.name); end;-- ATTRSORT::name STR::is_lt ATTRSORT::name
is_eq(b:SAME):BOOL is return name.is_eq(b.name); end;-- ATTRSORT::name STR::is_eq ATTRSORT::name
end;
class PRINT_OB
class PRINT_OB is
-- generates several functions that can be called from the
-- debugger or from a Sather program to visualize objects,
-- function frames and stack traces, either graphically
-- or textually. See the file Debugging in the Doc
-- directory on how to use those functions.
-- Original version by Claudio Fleiner <fleiner@icsi.berkeley.edu> 1.11.95
shared mangler:MANGLE;
shared funcs:FLIST{SIG};
private mang(ob:$OB):STR is
return mangler.mangle(ob,void);-- PRINT_OB::mangler MANGLE::mangle
end;
private mang(ob,ns:$OB):STR is
return mangler.mangle(ob,ns);-- PRINT_OB::mangler MANGLE::mangle
end;
mkfname(cl:$TP):FSTR is
return mang(cl).fstr;-- PRINT_OB::mang STR::fstr
end;
private get_ref_offsets(p:CODE_FILE,cl:$TP,el:$TP,prefix:STR) is
loop
e::=el.impl.elts.elt!;-- IMPL::elts ELT_TBL::elt!
if e.is_attr_reader then-- ELT::is_attr_reader
if ~e.ret.is_immutable and ~e.ret.is_bound and ~e.ret.is_external then-- ELT::ret BOOL::not ELT::ret BOOL::not ELT::ret BOOL::not
p+prefix+mang(e.name,el)+",";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang ELT::name CODE_FILE::plus
elsif e.ret.is_immutable then-- ELT::ret
get_ref_offsets(p,cl,e.ret,prefix+mang(e.name,el)+".");-- PRINT_OB::get_ref_offsets ELT::ret STR::plus PRINT_OB::mang ELT::name STR::plus
end
end;
end;
if el.is_immutable and ~void(el.impl) and ~void(el.impl.arr) then -- BOOL::not IMPL::arr BOOL::not
arr::=el.impl.arr.params[0];-- IMPL::arr TP_CLASS::params ARRAY{1}::aget
if ~arr.is_immutable and ~arr.is_bound and ~arr.is_external then-- BOOL::not BOOL::not BOOL::not
loop
i::=0.upto!(el.impl.asize_val-1);-- INT::upto! IMPL::asize_val INT::minus
p+prefix+"arr_part["+i+"]"+",";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
end;
elsif arr.is_immutable then
loop
i::=0.upto!(el.impl.asize_val-1);-- INT::upto! IMPL::asize_val INT::minus
get_ref_offsets(p,cl,arr,prefix+"arr_part["+i+"].");-- PRINT_OB::get_ref_offsets STR::plus STR::plus STR::plus
end;
end;
end;
end;
shared num_attr:INT:=0;
print(prog:PROG,cgen:CGEN):FSTR is
-- p:FSTR:=#(10000);
dec:FSTR:=#(1000);-- FSTR::create
mangler:=cgen.mangler;-- PRINT_OB::mangler CGEN::mangler
file_count::=0;
fc:INT; -- count number of function (we don't want too many, as
-- the declarations may be way to big if the file is split
p::=#CODE_FILE("Print"+file_count.str+".c");-- CODE_FILE::create STR::plus INT::str STR::plus
p.is_c_code:=true;-- CODE_FILE::is_c_code
clt::=prog.tp_tbl.class_tbl;-- PROG::tp_tbl TP_TBL::class_tbl
smallest_tag::=0;
largest_tag::=0;
loop
n::=cgen.tags.targets!;-- CGEN::tags FMAP{2}::targets!
if n<smallest_tag then smallest_tag:=n; end;-- INT::is_lt
if n>largest_tag then largest_tag:=n; end;-- INT::is_lt
end;
last_largest::=0;
last_smallest::=0;
tg::=0;
loop -- we want to create the tables for all tags, unfortunatly,
-- new tags can be touched during the loop
if tg>0 then-- INT::is_lt
if tg<largest_tag then-- INT::is_lt
tg:=tg+1;-- INT::plus
else
tg:=0;
end;
elsif tg<0 then-- INT::is_lt
if tg>smallest_tag then-- INT::is_lt
tg:=tg-1;-- INT::minus
else
tg:=0;
end;
end;
if tg=0 then-- INT::is_eq
if last_smallest=smallest_tag and last_largest=largest_tag then-- INT::is_eq INT::is_eq
if ~cgen.adjust_tag_table then break!; end;-- CGEN::adjust_tag_table BOOL::not
last_smallest:=smallest_tag;
last_largest:=largest_tag;
loop
n::=cgen.tags.targets!;-- CGEN::tags FMAP{2}::targets!
if n<smallest_tag then smallest_tag:=n; end;-- INT::is_lt
if n>largest_tag then largest_tag:=n; end;-- INT::is_lt
end;
end;
if last_largest<largest_tag then-- INT::is_lt
tg:=last_largest+1;-- INT::plus
last_largest:=largest_tag;
elsif last_smallest>smallest_tag then-- INT::is_lt
tg:=last_smallest-1;-- INT::minus
last_smallest:=smallest_tag;
else
break!;
end;
end;
cl:$TP:=void;
if tg/=0 then-- INT::is_eq BOOL::not
loop
pr::=cgen.tags.pairs!;-- CGEN::tags FMAP{2}::pairs!
if pr.t2=tg then-- TUP{2}::t2 INT::is_eq
cl:=pr.t1;-- TUP{2}::t1
break!;
end;
end;
if void(cl) then
prog.barf("there seems to be no type for tag "+tg+"\n");-- PROG::barf STR::plus STR::plus
end;
if fc=30 then-- INT::is_eq
file_count:=file_count+1;-- INT::plus
p:=#CODE_FILE("Print"+file_count.str+".c");-- CODE_FILE::create STR::plus INT::str STR::plus
p.is_c_code:=true;-- CODE_FILE::is_c_code
fc:=0;
end;
fc:=fc+1;-- INT::plus
if ~void(cl) then-- BOOL::not
p.uses_tp(cl);-- CODE_FILE::uses_tp
fname::=mkfname(cl);-- PRINT_OB::mkfname
as:ARRAY{ATTRSORT};
attrs::=0;
if ~cl.is_abstract and ~void(cl.impl) then-- BOOL::not BOOL::not
as:=#ARRAY{ATTRSORT}(cl.impl.elts.size);-- ARRAY{1}::create IMPL::elts ELT_TBL::size
loop
n::=cl.impl.elts.elt!.name.str;-- IMPL::elts ELT_TBL::elt! ELT::name IDENT::str
c::=cl.impl.elts.elt!;-- IMPL::elts ELT_TBL::elt!
if c.is_attr_reader then-- ELT::is_attr_reader
as.set!(#(n,c)); -- ARRAY{1}::set! ATTRSORT::create
attrs:=attrs+1;-- INT::plus
end;
end;
as:=as.resize(attrs);-- ARRAY{1}::resize
as.sort;-- ARRAY{1}::sort
end;
p:=p+"\n/* type information for "+cl.str+" */\n";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
p:=p+"static int "+fname+"_ref_offsets[]= {";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
if cl.is_subtype(TP_BUILTIN::dollar_lock) then-- TP_BUILTIN::dollar_lock
p:=p+"LOCK_HEADER_STRUCT_REFS ";-- CODE_FILE::plus
end;
if ~cl.is_abstract and ~cl.is_bound and ~cl.is_external then -- BOOL::not BOOL::not BOOL::not
tps:STR;
if cl.is_immutable then tps:="\n (int)&(*("+mang(cl)+"*)0).";-- STR::plus PRINT_OB::mang STR::plus
else tps:="\n (int)&(*("+mang(cl)+")0)."; end;-- STR::plus PRINT_OB::mang STR::plus
get_ref_offsets(p,cl,cl,tps); -- PRINT_OB::get_ref_offsets
end;
p:=p+"\t-1};\n";-- CODE_FILE::plus
p:=p+"struct { int *refs;char *sn,*cn;long src;int sz,bx,at;\n"+-- CODE_FILE::plus
" unsigned is_val:1,is_ref:1,is_abs:1,is_bnd:1,is_ext:1,is_aref:1;";-- CODE_FILE::plus
if ~void(cl.impl) and ~void(cl.impl.arr) then attrs:=attrs+2; end;-- BOOL::not IMPL::arr BOOL::not INT::plus
if attrs>0 then-- INT::is_lt
p:=p+"\n struct sather_attribute attr["+attrs+"];";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
end;
p:=p+" } "+fname+"_type_table = {\n";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
p:=p+" "+fname+"_ref_offsets,\n"-- CODE_FILE::plus CODE_FILE::plus
+" \""+cl.str+"\", \"";-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
if ~cl.is_external then p:=p+mang(cl); end;-- BOOL::not CODE_FILE::plus PRINT_OB::mang
typecase cl when TP_CLASS then
p:=p+"\",\n "+filepos(prog.parse.tree_for(cl.name,cl.params.size).source)+",\n";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::filepos PROG::parse TP_CLASS::name TP_CLASS::params ARRAY{1}::size AS_CLASS_DEF::source CODE_FILE::plus
else
p:=p+"\",\n 0,\n";-- CODE_FILE::plus
end;
if cl.is_immutable then
p:=p+" sizeof("+mang(cl)+"),(int)&((*("+mang(cl)+"_boxed)NULL).immutable_part),";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang CODE_FILE::plus
else
if cl.str="EXT_OB" then-- STR::is_eq
p+" 0,0, /* sizeof *EXT_OB is unkown */\n";-- CODE_FILE::plus
elsif cl.is_external then
p:=p+" 0,0, /* externals have no size */\n";-- CODE_FILE::plus
elsif ~void(cl.impl) and ~void(cl.impl.arr) then-- BOOL::not IMPL::arr BOOL::not
p:=p+" (int)(*("+mang(cl)+")0).arr_part,0, /* size without array */\n"-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang
else-- CODE_FILE::plus
p:=p+" sizeof(*("+mang(cl)+")0),0,\n";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang CODE_FILE::plus
end;
end;
if ~void(cl.impl) and ~void(cl.impl.arr) then p+" "+(attrs-2); else p+" "+attrs; end;-- BOOL::not IMPL::arr BOOL::not CODE_FILE::plus CODE_FILE::plus INT::minus CODE_FILE::plus CODE_FILE::plus
if cl.is_immutable then p:=p+" ,1"; else p:=p+" ,0"; end;-- CODE_FILE::plus CODE_FILE::plus
if ~cl.is_immutable and ~cl.is_abstract and ~cl.is_bound and ~cl.is_external then p:=p+",1"; else p:=p+",0"; end;-- BOOL::not BOOL::not BOOL::not BOOL::not CODE_FILE::plus CODE_FILE::plus
if cl.is_abstract then p:=p+",1"; else p:=p+",0"; end;-- CODE_FILE::plus CODE_FILE::plus
if cl.is_bound then p:=p+",1"; else p:=p+",0"; end;-- CODE_FILE::plus CODE_FILE::plus
if cl.is_external then p:=p+",1"; else p:=p+",0"; end;-- CODE_FILE::plus CODE_FILE::plus
if ~void(cl.impl) and ~void(cl.impl.arr) then p:=p+",1"; else p:=p+",0"; end;-- BOOL::not IMPL::arr BOOL::not CODE_FILE::plus CODE_FILE::plus
if ~cl.is_abstract and ~void(cl.impl) and attrs>0 then-- BOOL::not BOOL::not INT::is_lt
p+",\n {\n";-- CODE_FILE::plus
first::=true;
i::=1;
loop e::=as.elt!.elt;-- ARRAY{1}::elt! ATTRSORT::elt
if e.is_attr_reader then-- ELT::is_attr_reader
if first then first:=false else p+",\n"; end;-- CODE_FILE::plus
p+" { \""+ e.name.str+"\",\""+mang(e.name,cl)+"\","-- CODE_FILE::plus CODE_FILE::plus ELT::name IDENT::str CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang ELT::name
+cgen.tag_for(e.ret)+",(int)&(*("+mang(cl);-- CODE_FILE::plus CODE_FILE::plus CGEN::tag_for ELT::ret CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang
if cl.is_immutable then p:=p+"*"; end;-- CODE_FILE::plus
p:=p+")0)."+mang(e.name,cl);-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang ELT::name
p:=p+","+filepos(e.as.source)+" }";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::filepos ELT::as CODE_FILE::plus
end
end;
if ~void(cl.impl.arr) then-- IMPL::arr BOOL::not
if first then first:=false else p+",\n"; end;-- CODE_FILE::plus
-- note that for value arrays the offset is the
-- size of the array! (asize is not an attribute of a
-- value array)
p:=p+" { \"asize\",\"asize\",INT_tag,";-- CODE_FILE::plus
if cl.is_immutable then
p:=p+mang(cl)+"_ASIZE,";-- CODE_FILE::plus PRINT_OB::mang CODE_FILE::plus
else
p:=p+"(int)&(*("+mang(cl)+")0).asize,";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang CODE_FILE::plus
end;
p:=p+"0 }";-- CODE_FILE::plus
arr::=cl.impl.arr.params[0];-- IMPL::arr TP_CLASS::params ARRAY{1}::aget
p:=p+",\n { \"[]\",\"arr_part[]\","+cgen.tag_for(arr)+-- CODE_FILE::plus CODE_FILE::plus CGEN::tag_for
",(int)(*("+mang(cl);-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang
if cl.is_immutable then p:=p+"*"; end;-- CODE_FILE::plus
p:=p+")0).arr_part,0 }";-- CODE_FILE::plus
end;
p:=p+"\n }";-- CODE_FILE::plus
end;
p:=p+"\n};\n";-- CODE_FILE::plus
p.good_place_to_split;-- CODE_FILE::good_place_to_split
end;
end;
end;
dec:=dec+"\n#define NUM_OF_ATTR "+num_attr+"\n";-- FSTR::plus PRINT_OB::num_attr FSTR::plus
print_sather_type(prog,cgen,smallest_tag,largest_tag);-- PRINT_OB::print_sather_type
print_file_list(prog,cgen,p);-- PRINT_OB::print_file_list
if cgen.func_tables then print_sather_func(prog,cgen); end;-- CGEN::func_tables PRINT_OB::print_sather_func
return dec;
end;
print_sather_type(prog:PROG,cgen:CGEN,sm:INT,lg:INT) is
c::=#CODE_FILE("sather_type.c");-- CODE_FILE::create
c.is_c_code:=true;-- CODE_FILE::is_c_code
c.do_not_merge:=true;-- CODE_FILE::do_not_merge
decl:FSTR:=#(1000);-- FSTR::create
p:FSTR:=#(10000);-- FSTR::create
p:=p+"static struct sather_type_description *sather_types_static[] = {\n";-- FSTR::plus
decl:=decl+"#define ESS extern struct sather_type_description\n";-- FSTR::plus
loop
tg::=sm.upto!(lg);-- INT::upto!
if tg=0 then-- INT::is_eq
p:=p+" NULL, /* no type has tag 0 */\n";-- FSTR::plus
else
cl:$TP;
loop
pr::=cgen.tags.pairs!;-- CGEN::tags FMAP{2}::pairs!
if pr.t2=tg then-- TUP{2}::t2 INT::is_eq
cl:=pr.t1;-- TUP{2}::t1
break!;
end;
end;
if void(cl) then
prog.barf("there seems to be no type for tag "+tg+"\n");-- PROG::barf STR::plus STR::plus
end;
fname::=mkfname(cl);-- PRINT_OB::mkfname
decl:=decl+"ESS "+fname+"_type_table;\n";-- FSTR::plus FSTR::plus FSTR::plus
p:=p+" &"+fname+"_type_table,\n";-- FSTR::plus FSTR::plus FSTR::plus
end;
end;
p:=p+" NULL };\n";-- FSTR::plus
-- p:=p+"int sather_type_offset= ("+(-sm)+");\n";
p:=p+"struct sather_type_description **sather_types = sather_types_static+"+(-sm)+";\n";-- FSTR::plus FSTR::plus INT::negate FSTR::plus
c+decl+"\n"+p;-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
end;
sort(t1,t2:TUP{SIG,INT}):BOOL is
return t1.t1.str<t2.t1.str;-- TUP{2}::t1 SIG::str STR::is_lt TUP{2}::t1 SIG::str
end;
print_sather_func(prog:PROG,cgen:CGEN) is
-- Generate FUNC()
c::=#CODE_FILE("sather_func.c");-- CODE_FILE::create
c.is_c_code:=true;-- CODE_FILE::is_c_code
c.do_not_merge:=true;-- CODE_FILE::do_not_merge
cs:ARRAY{TUP{SIG,INT}}:=#(funcs.size);-- ARRAY{1}::create PRINT_OB::funcs FLIST{1}::size
loop
cs.set!(#TUP{SIG,INT}(funcs.elt!,0.up!));-- ARRAY{1}::set! TUP{2}::create PRINT_OB::funcs FLIST{1}::elt! INT::up!
end;
cs.insertion_sort_by(bind(sort(_,_)));-- ARRAY{1}::insertion_sort_by PRINT_OB::sort
loop
cgen.tags_h+("#define F_tag_"+cs.elt!.t2+" "+0.up!+"\n");-- CGEN::tags_h CODE_FILE::plus STR::plus ARRAY{1}::elt! TUP{2}::t2 STR::plus STR::plus INT::up! STR::plus
end;
c+"#define ES extern struct sather_function_definition\n";-- CODE_FILE::plus
loop
c+("ES "+mang(cs.elt!.t1)+"_iframe;\n");-- CODE_FILE::plus STR::plus PRINT_OB::mang ARRAY{1}::elt! TUP{2}::t1 STR::plus
end;
c+"\n";-- CODE_FILE::plus
c+"struct sather_function_definition *sather_functions[] = {\n";-- CODE_FILE::plus
loop
c+(" &"+mang(cs.elt!.t1)+"_iframe,\n");-- CODE_FILE::plus STR::plus PRINT_OB::mang ARRAY{1}::elt! TUP{2}::t1 STR::plus
end;
c+" NULL\n};\n";-- CODE_FILE::plus
end;
-- print out the list of source files as an array
print_file_list(prog:PROG,cgen:CGEN,p:CODE_FILE) is
p+"char *source_files[] = {\n";-- CODE_FILE::plus
loop
p+(" \""+SFILE_ID::files.elt!+"\",\n");-- CODE_FILE::plus STR::plus SFILE_ID::files FLIST{1}::elt! STR::plus
end;
p+"};\n";-- CODE_FILE::plus
end;
filepos(s:SFILE_ID):INT is
return s.index*1048576+s.line_num_in;-- SFILE_ID::index INT::times INT::plus SFILE_ID::line_num_in
end;
register(s:SIG):STR is
funcs:=funcs.push(s); -- PRINT_OB::funcs PRINT_OB::funcs FLIST{1}::push
return "F_tag_"+(funcs.size-1);-- STR::plus PRINT_OB::funcs FLIST{1}::size INT::minus
end;
print_frame(prog:PROG,cgen:CGEN,p:CODE_FILE,o:AM_ROUT_DEF,iout:FLIST{AM_LOCAL_EXPR}) is
mangler:=cgen.mangler;-- PRINT_OB::mangler CGEN::mangler
n::=0;
args::=o.size;-- AM_ROUT_DEF::size
locals::=0;
loop
l::=o.locals.elt!;-- AM_ROUT_DEF::locals FLIST{1}::elt!
if l/=o.rres and ~void(l.name) then-- AM_LOCAL_EXPR::is_eq AM_ROUT_DEF::rres BOOL::not AM_LOCAL_EXPR::name BOOL::not
locals:=locals+1;-- INT::plus
end;
end;
p+"\nstruct { void (*cf)();long src;char *sn,*cn;int args,lc;";-- CODE_FILE::plus
if args+locals>0 then-- INT::plus INT::is_lt
p+"\n struct sather_attribute attr["+(locals+args)+"];";-- CODE_FILE::plus CODE_FILE::plus INT::plus CODE_FILE::plus
end;
p+" } "+mang(o.sig)+"_iframe = {\n";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang AM_ROUT_DEF::sig CODE_FILE::plus
p+" (void (*)())"+mang(o.sig)+",\n";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang AM_ROUT_DEF::sig CODE_FILE::plus
p+" "+filepos(o.source)+",\n";-- CODE_FILE::plus CODE_FILE::plus PRINT_OB::filepos AM_ROUT_DEF::source CODE_FILE::plus
p+" \""+o.sig.str+"\",\""+mang(o.sig)+"\",\n";-- CODE_FILE::plus CODE_FILE::plus AM_ROUT_DEF::sig SIG::str CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang AM_ROUT_DEF::sig CODE_FILE::plus
p+" "+args+", "+locals;-- CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus CODE_FILE::plus
if args+locals>0 then-- INT::plus INT::is_lt
p+",\n {";-- CODE_FILE::plus
first::=true;
loop i::=o.ind!;-- AM_ROUT_DEF::ind!
n:=n+1;-- INT::plus
if ~first then p+","; end;-- BOOL::not CODE_FILE::plus
first:=false;
s::=o[i].expr;-- AM_ROUT_DEF::aget AM_FORMAL_ARG::expr
if o.sig.is_iter and (o[i].mode=MODES::inout_mode or o[i].mode=MODES::out_mode) then-- AM_ROUT_DEF::sig SIG::is_iter AM_ROUT_DEF::aget AM_FORMAL_ARG::mode MODES::inout_mode AM_ROUT_DEF::aget AM_FORMAL_ARG::mode MODES::out_mode
s:=iout.elt!;-- FLIST{1}::elt!
end;
p+"\n { \""+o[i].name.str+"\",\""+mang(s,o.sig)+"\",";-- CODE_FILE::plus CODE_FILE::plus AM_ROUT_DEF::aget AM_FORMAL_ARG::name IDENT::str CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang AM_ROUT_DEF::sig CODE_FILE::plus
p+cgen.tag_for(o[i].tp)+",0,"+filepos(o.source)+" }";-- CODE_FILE::plus CGEN::tag_for AM_ROUT_DEF::aget AM_FORMAL_ARG::tp CODE_FILE::plus CODE_FILE::plus PRINT_OB::filepos AM_ROUT_DEF::source CODE_FILE::plus
end;
loop
l::=o.locals.elt!;-- AM_ROUT_DEF::locals FLIST{1}::elt!
if l/=o.rres and ~void(l.name) then-- AM_LOCAL_EXPR::is_eq AM_ROUT_DEF::rres BOOL::not AM_LOCAL_EXPR::name BOOL::not
n:=n+1;-- INT::plus
if ~first then p+","; end;-- BOOL::not CODE_FILE::plus
first:=false;
p+"\n { \""+l.name.str+"\",\""+mang(l,o.sig)+"\",";-- CODE_FILE::plus CODE_FILE::plus AM_LOCAL_EXPR::name IDENT::str CODE_FILE::plus CODE_FILE::plus PRINT_OB::mang AM_ROUT_DEF::sig CODE_FILE::plus
p+cgen.tag_for(l.tp)+",0,"+filepos(l.source)+" }";-- CODE_FILE::plus CGEN::tag_for AM_LOCAL_EXPR::tp CODE_FILE::plus CODE_FILE::plus PRINT_OB::filepos AM_LOCAL_EXPR::source CODE_FILE::plus
end;
end;
p+"\n }";-- CODE_FILE::plus
end;
p+"\n};\n";-- CODE_FILE::plus
if n>num_attr then num_attr:=n; end;-- PRINT_OB::num_attr PRINT_OB::num_attr
end;
end;
-- vim:sw=3:nosmartindent