# perl module for generating C code. # arch-tag: d80bc4c9-0bf3-4786-878b-63905f0bcb29 package CGenerator; use strict; use Getopt::Std; #use Data::Dumper; sub new ($) { bless { Name => $_[0], cd => "", hd => "", enums => {}, cinc => [], hinc => [], cbody => [], hbody => [], structs => {}, funs => {} } } sub gen_comment () { printf "/* generated by %s at %s */\n", $0, scalar(localtime); } sub cquote ($) { ($_) = @_; s/^"/\\"/; s/([^\\])"/$1\\"/g; return "\"$_\""; } sub c { my $self = shift; $self->{cd} .= "$_[0]\n"; } sub cb { my $self = shift; push @{$self->{cbody}},$_[0]; } sub h { my $self = shift; $self->{hd} .= "$_[0]\n"; } sub dd { my ($self, $decl, $value) = @_; $self->c(sprintf "%s%s;", $decl, $value ? " = $value" : "" ); $self->h(sprintf "extern %s;", $decl) if $decl !~ /static/; } sub enum { my $self = shift; push @{$self->{enums}{$_[0]}},$_[1]; } sub struct { my $self = shift; push @{$self->{structs}{$_[0]}},$_[1]; } sub fun { my $self = shift; my $f = shift; push @{$self->{funs}{$f}{body}},@_; } sub fund { my $self = shift; my $f = shift; $self->{funs}{$f}{ret} = shift; $self->{funs}{$f}{proto} = [@_]; } sub hinc { my ($self,$fn,$local) = @_; push @{$self->{hinc}}, $local ? "\"$fn\"" : "<$fn>"; } sub cinc { my ($self,$fn,$local) = @_; push @{$self->{cinc}}, $local ? "\"$fn\"" : "<$fn>"; } sub gen_headers { my $prev = ""; my @hi = grep($_ ne $prev && ($prev = $_, 1), sort @_); foreach (@hi) { next if /^\"/; print "#include $_\n"; } print "\n"; foreach (@hi) { next unless /^\"/; print "#include $_\n"; } } sub gen_body { my %saw; my @out = grep(!$saw{$_}++, @_); map { print "$_\n\n" } @out; } sub gen_c { my $self = shift; gen_comment(); gen_headers(@{$self->{cinc}}); print "#include \"$self->{Name}.h\"\n\n"; print $self->{cd}; gen_body(@{$self->{cbody}}); foreach (keys %{$self->{funs}}) { my %v = %{$self->{funs}{$_}}; print "$v{ret}\n$_" . "(" . ((join ", ", @{$v{proto}}) || "void") . ")\n{\n"; foreach (@{$v{body}}) { print "\t$_\n"; } print "}\n\n"; } } sub gen_h { my $self = shift; my $Name = uc $self->{Name}; gen_comment(); print "#ifndef ${Name}_H\n"; print "#define ${Name}_H\n\n"; gen_headers(@{$self->{hinc}}); foreach (keys %{$self->{enums}}) { my @v = @{$self->{enums}{$_}}; print "enum $_ { ", (join ", ",@v), " };\n"; } foreach (keys %{$self->{structs}}) { my @v = @{$self->{structs}{$_}}; print "struct $_ {\n"; map { print "\t$_;\n"; } @v; print "};\n\n"; } print $self->{hd}; foreach (keys %{$self->{funs}}) { my %v = %{$self->{funs}{$_}}; next if $v{ret} =~ /static/; print "$v{ret} $_" . "(" . ((join ", ", @{$v{proto}}) || "void") . ");\n"; } print "\n#endif\n"; } sub show { my $self = shift; my $o = shift; #Getopt::Std::getopts("ch", \%o); $self->gen_c if $o->{c}; $self->gen_h if $o->{h}; } 1;