From 3f39e285d06dba8ff9a64aa4a0cd628a888dd786 Mon Sep 17 00:00:00 2001 From: jj Date: Tue, 3 Apr 2012 16:09:29 +0200 Subject: [PATCH] codegen: gen cpp helper --- plugins/ruby/codegen.pl | 117 +++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl index e7052f472..58d97342f 100755 --- a/plugins/ruby/codegen.pl +++ b/plugins/ruby/codegen.pl @@ -6,7 +6,9 @@ use warnings; use XML::LibXML; our @lines_rb; -our @lines_cpp; +my @lines_cpp; +my @include_cpp; +my %offsets; sub indent_rb(&) { my ($sub) = @_; @@ -99,52 +101,56 @@ sub render_bitfield_fields { } +my $cpp_var_count = 0; sub render_global_class { my ($name, $type) = @_; - #my $cppvar = 'v'; # for offsetof + my $cppvar = "v_$cpp_var_count"; + $cpp_var_count += 1; + push @lines_cpp, "df::$name $cppvar;"; + push @include_cpp, $name; my $rbname = rb_ucase($name); my $parent = rb_ucase($type->getAttribute('inherits-from') || 'MemStruct'); push @lines_rb, "class $rbname < $parent"; indent_rb { - render_struct_fields($type); + render_struct_fields($type, $cppvar); }; push @lines_rb, "end"; } sub render_struct_fields { - my ($type) = @_; + my ($type, $cppvar) = @_; for my $field ($type->findnodes('child::ld:field')) { my $name = $field->getAttribute('name'); $name = $field->getAttribute('ld:anon-name') if (!$name); next if (!$name); - my $offset = "'TODOoffsetof_$name'"; + my $offset = get_offset($cppvar, $name); push @lines_rb, "field(:$name, $offset) {"; indent_rb { - render_item($field); + render_item($field, "$cppvar.$name"); }; push @lines_rb, "}"; } } sub render_item { - my ($item) = @_; + my ($item, $cppvar) = @_; return if (!$item); my $meta = $item->getAttribute('ld:meta'); my $renderer = $item_renderer{$meta}; if ($renderer) { - $renderer->($item); + $renderer->($item, $cppvar); } else { print "no render item $meta\n"; } } sub render_item_global { - my ($item) = @_; + my ($item, $cppvar) = @_; my $typename = $item->getAttribute('type-name'); my $rbname = rb_ucase($typename); @@ -153,7 +159,7 @@ sub render_item_global { } sub render_item_number { - my ($item) = @_; + my ($item, $cppvar) = @_; my $subtype = $item->getAttribute('ld:subtype'); $subtype = $item->getAttribute('base-type') if ($subtype eq 'enum'); @@ -183,14 +189,14 @@ sub render_item_number { } sub render_item_compound { - my ($item) = @_; + my ($item, $cppvar) = @_; my $subtype = $item->getAttribute('ld:subtype'); if (!$subtype || $subtype eq 'bitfield') { push @lines_rb, "compound {"; indent_rb { if (!$subtype) { - render_struct_fields($item); + render_struct_fields($item, $cppvar); } else { render_bitfield_fields($item); } @@ -200,23 +206,23 @@ sub render_item_compound { # declare constants render_enum_fields($item); # actual field - render_item_number($item); + render_item_number($item, $cppvar); } else { print "no render compound $subtype\n"; } } sub render_item_container { - my ($item) = @_; + my ($item, $cppvar) = @_; my $subtype = $item->getAttribute('ld:subtype'); my $rbmethod = join('_', split('-', $subtype)); my $tg = $item->findnodes('child::ld:item')->[0]; if ($tg) { - my $tglen = get_tglen($tg); + my $tglen = get_tglen($tg, $cppvar); push @lines_rb, "$rbmethod($tglen) {"; indent_rb { - render_item($tg); + render_item($tg, "${cppvar}[0]"); }; push @lines_rb, "}"; } else { @@ -225,32 +231,32 @@ sub render_item_container { } sub render_item_pointer { - my ($item) = @_; + my ($item, $cppvar) = @_; my $tg = $item->findnodes('child::ld:item')->[0]; - my $tglen = get_tglen($tg); + my $tglen = get_tglen($tg, $cppvar); push @lines_rb, "pointer($tglen) {"; indent_rb { - render_item($tg); + render_item($tg, "${cppvar}[0]"); }; push @lines_rb, "}"; } sub render_item_staticarray { - my ($item) = @_; + my ($item, $cppvar) = @_; my $count = $item->getAttribute('count'); my $tg = $item->findnodes('child::ld:item')->[0]; - my $tglen = get_tglen($tg); + my $tglen = get_tglen($tg, $cppvar); push @lines_rb, "static_array($count, $tglen) {"; indent_rb { - render_item($tg); + render_item($tg, "${cppvar}[0]"); }; push @lines_rb, "}"; } sub render_item_primitive { - my ($item) = @_; + my ($item, $cppvar) = @_; my $subtype = $item->getAttribute('ld:subtype'); if ($subtype eq 'stl-string') { @@ -261,7 +267,7 @@ sub render_item_primitive { } sub render_item_bytes { - my ($item) = @_; + my ($item, $cppvar) = @_; my $subtype = $item->getAttribute('ld:subtype'); if ($subtype eq 'padding') { @@ -274,9 +280,18 @@ sub render_item_bytes { } +sub get_offset { + my ($cppvar, $fname) = @_; + + return query_cpp("offsetof(typeof($cppvar), $fname)"); +} + sub get_tglen { - my ($tg) = @_; - if (!$tg) { return 'nil'; } + my ($tg, $cppvar) = @_; + + if (!$tg) { + return query_cpp("sizeof(${cppvar}[0])"); + } my $meta = $tg->getAttribute('ld:meta'); if ($meta eq 'number') { @@ -284,14 +299,40 @@ sub get_tglen { } elsif ($meta eq 'pointer') { return 4; } else { - # TODO - return "'TODOsizeof($meta)'"; + return query_cpp("sizeof(${cppvar}[0])"); } } +sub query_cpp { + my ($query) = @_; + + my $ans = $offsets{$query}; + return $ans if ($ans); + + push @lines_cpp, "cout << \"$query = \" << $query << endl;"; + return "'$query'"; +} + + + my $input = $ARGV[0] || '../../library/include/df/codegen.out.xml'; -my $output_rb = $ARGV[1] || 'ruby-autogen.rb'; -my $output_cpp = $ARGV[2] || 'ruby-autogen.cpp'; + +# run once with output = 'ruby-autogen.cpp' +# compile +# execute, save output to 'ruby-autogen.offsets' +# re-run this script with output = 'ruby-autogen.rb' and offsetfile = 'ruby-autogen.offsets' +# delete binary +# delete offsets +my $output = $ARGV[1] or die "need output file"; +my $offsetfile = $ARGV[2]; + +if ($offsetfile) { + while (<$offsetfile>) { + my @val = split(' = '); + $offsets{$val[0]} = $val[1]; + } +} + my $doc = XML::LibXML->new()->parse_file($input); my %global_types; @@ -310,12 +351,16 @@ for my $name (sort { $a cmp $b } keys %global_types) { for my $obj ($doc->findnodes('/ld:data-definition/ld:global-object')) { my $name = $obj->getAttribute('name'); + # TODO } -open FH, ">$output_rb"; -print FH "$_\n" for @lines_rb; -close FH; - -open FH, ">$output_cpp"; -print FH "$_\n" for @lines_cpp; +open FH, ">$output"; +if ($output =~ /\.cpp$/) { + print FH "#include \"$_\"\n" for @include_cpp; + print FH "void main(void) {\n"; + print FH " $_\n" for @lines_cpp; + print FH "}\n"; +} else { + print FH "$_\n" for @lines_rb; +} close FH;