summaryrefslogtreecommitdiff
path: root/src/itf2h.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/itf2h.pl')
-rwxr-xr-xsrc/itf2h.pl146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/itf2h.pl b/src/itf2h.pl
new file mode 100755
index 0000000..9ebce65
--- /dev/null
+++ b/src/itf2h.pl
@@ -0,0 +1,146 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+
+# itf1 => { name, comment, methods, signals, properties }, ...
+# methods = [ { name, comment, flags, in => [ [ type, name ], .. ], out }, .. ]
+# signals = [ { name, comment, args => [ [ type, name ], .. ] }, .. ]
+# properties = [ { type, name, comment }, .. ]
+sub read_itf {
+ my %itf;
+ my $itf;
+ my $comment = '';
+ my $sect;
+
+ while(<>) {
+ chomp;
+ s/[\s\t]+/ /g;
+ s/ $//;
+ next if !$_;
+
+ # Comment
+ if(/^ *#(.+)$/) {
+ $comment = "\n" if !$comment;
+ $comment .= $1;
+ next;
+ }
+
+ # New interface
+ if(/^([^ ]+) ([^ ]+)$/) {
+ $itf = $1;
+ $itf{$itf} = { name => $2, comment => $comment, map +($_=>[]), qw|methods signals properties| };
+ $comment = '';
+ $sect = '';
+ next;
+ }
+ die "Unknown directive or not in an interface: $_\n" if !$itf;
+
+ # Section switcher
+ if(/^ -- (methods|signals|properties)$/) {
+ $sect = $1;
+ next;
+ }
+ die "Unknown directive or not in a section: $_\n" if !$sect;
+
+ # Method start
+ if($sect eq 'methods' && /^ ([^ ]+)(?: \[([^ ]+)\])?$/) {
+ push @{$itf{$itf}{methods}}, { name => $1, comment => $comment, flags => $2, in => [], out => [] };
+ $comment = '';
+ next;
+ }
+
+ # Method arg
+ if($sect eq 'methods' && /^ (in|out) ([^ ]+) ([^ ]+)$/) {
+ die "Argument before method name: $_\n" if !@{$itf{$itf}{methods}};
+ push @{$itf{$itf}{methods}[$#{$itf{$itf}{methods}}]{$1}}, [ $2, $3 ];
+ next;
+ }
+
+ # Signal start
+ if($sect eq 'signals' && /^ ([^ ]+)(?: \[([^ ]+)\])?$/) {
+ push @{$itf{$itf}{signals}}, { name => $1, comment => $comment, flags => $2, args => [] };
+ $comment = '';
+ next;
+ }
+
+ # Signal arg
+ if($sect eq 'signals' && /^ ([^ ]+) ([^ ]+)$/) {
+ die "Argument before signal name: $_\n" if !@{$itf{$itf}{signals}};
+ push @{$itf{$itf}{signals}[$#{$itf{$itf}{signals}}]{args}}, [ $1, $2 ];
+ next;
+ }
+
+ # Properties
+ if($sect eq 'properties' && /^ ([^ ]+) ([^ ]+) ([^ ]+)$/) {
+ push @{$itf{$itf}{properties}}, { type => $1, name => $2, flags => $3, comment => $comment };
+ $comment = '';
+ next;
+ }
+
+ die "Unknown directive: $_\n";
+ }
+
+ return %itf;
+}
+
+
+sub write_h {
+ my %itf = @_;
+
+ my $argl = sub {
+ my($n, $a) = @_;
+ printf "static char *_itf_%s[] = {\n\t", $n;
+ print join ', ', map(qq{"$_->[0]", "$_->[1]"}, @$a), 'NULL';
+ print "\n};\n";
+ };
+
+ my $flags = sub {
+ my $f = shift->{flags}||'';
+ return join '|', 0, map $f=~/$_/?("ITFF_\U$_"):(), qw|deprecated noreply read write emitnone emitchange|;
+ };
+
+ print "/* File automatically generated by itf2h.pl, DO NOT EDIT. */\n\n";
+ for my $itf (keys %itf) {
+ printf "\n#if !defined(ITF_IMPL_%s) && !defined(ITF_IMPL_ALL)\n", $itf;
+ printf "extern itf_t *itf_%s;\n", $itf;
+ printf "#else\n\n", $itf;
+
+ # Method arguments
+ for my $m (@{$itf{$itf}{methods}}) {
+ $argl->(sprintf("%s_%s_%s", $itf, $m->{name}, $_), $m->{$_}) for ('in', 'out');
+ }
+
+ # Method list
+ printf "\nstatic itf_method_t _itf_%s_methods[] = {", $itf;
+ print join ",", map sprintf("\n\t".'{"%2$s", %3$s, _itf_%1$s_%2$s_in, _itf_%1$s_%2$s_out}', $itf, $_->{name}, $flags->($_)), @{$itf{$itf}{methods}};
+ print "\n};\n\n";
+
+ # Signal arguments
+ $argl->(sprintf("%s_%s_args", $itf, $_->{name}), $_->{args}) for (@{$itf{$itf}{signals}});
+
+ # Signal list
+ printf "\nstatic itf_signal_t _itf_%s_signals[] = {", $itf;
+ print join ",", map sprintf("\n\t".'{"%2$s", %3$s, _itf_%1$s_%2$s_args}', $itf, $_->{name}, $flags->($_)), @{$itf{$itf}{signals}};
+ print "\n};\n";
+
+ # Properties
+ printf "\nstatic itf_property_t _itf_%s_properties[] = {", $itf;
+ print join ",", map sprintf("\n\t".'{"%s", "%s", %s}', $_->{name}, $_->{type}, $flags->($_)), @{$itf{$itf}{properties}};
+ print "\n};\n\n";
+
+ # The interface object
+ printf "itf_t _itf_%s = {\n", $itf;
+ printf "\t\"%s\",\n", $itf{$itf}{name};
+ printf "\t%d, %d, %d,\n", scalar @{$itf{$itf}{methods}}, scalar @{$itf{$itf}{signals}}, scalar @{$itf{$itf}{properties}};
+ printf "\t".'_itf_%s_methods, _itf_%1$s_signals, _itf_%1$s_properties'."\n", $itf;
+ print "};\n";
+ printf "itf_t *itf_%s = &_itf_%1\$s;\n\n", $itf;
+
+ printf "#endif /* ITF_IMPL_%s */\n\n", $itf;
+ }
+}
+
+my %interfaces = read_itf;
+write_h(%interfaces);