#!/usr/bin/perl
+use File::Basename;
+
use Data::Dumper;
+my $scriptPath = dirname(__FILE__);
+push @INC,$scriptPath;
+
+require genconfig;
+require genconfig2;
+
my @includes = ();
my $header;
my $control = "api-defines.def";
my $output;
+my $hackformat;
while (@ARGV) {
my $cmd = shift;
$verbose++;
} elsif ($cmd eq "-I") {
push @includes, shift;
+ } elsif ($cmd eq "--hack-new-format") {
+ $hackformat = 1;
+ } elsif ($cmd eq "--hack-new-format-2") {
+ $hackformat = 2;
} else {
$control = $cmd;
}
die ("no output specified") if !$output;
-my $defs = loadControlFile($control);
-my @exports = @{$defs->{define}};
+my $defs;
+my @xports;
+if ($hackformat == 1) {
+ $defs = genconfig::loadControlFile($control);
+ @exports = grep { $_->{type} eq 'define' } @{$defs};
+} elsif ($hackformat == 2) {
+ push @includes, $scriptPath;
+ my $conf = new genconfig2({ include => \@includes }, $control);
+ $defs = $conf->{objects};
+ @exports = grep { $_->{type} eq 'define' } @{$defs};
+} else {
+ $defs = loadControlFile($control);
+ @exports = @{$defs->{define}};
+}
my %rawDefines = (); # indexed by header
my $CPPFLAGS = "";
# definition.
print $fp <<END;
/* note unsigned types are output as signed for java compatability */
+/* unsigned long long might not be 64 bit i guess, could use sizeof i suppose */
#define FMT(x) \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), float), "value=>%a, type=>'f32'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), double), "value=>%a, type=>'f64'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int32_t), "value=>%d, type=>'i32'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), uint32_t), "value=>%d, type=>'u32'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int64_t), "value=>%ld, type=>'i64'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), uint64_t), "value=>%ld, type=>'u64'", \\
- __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), typeof(char[])), "value=>'%s', type=>'string'", "type => undefined" )))))))
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), float), "value=>'%a', type=>'f32'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), double), "value=>'%a', type=>'f64'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int32_t), "value=>'%d', type=>'i32'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), uint32_t), "value=>'0x%08x', type=>'u32'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int64_t), "value=>'%ld', type=>'i64'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), uint64_t), "value=>'0x%016lx', type=>'u64'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), unsigned long long), "value=>'0x%016llx', type=>'u64'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), long long), "value=>'0x%016llx', type=>'i64'", \\
+ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), typeof(char[])), "value=>'%s', type=>'string'", "type => undefined" )))))))))
int main(int argc, char **argv) {
FILE *fp = fopen(argv[1], "w");
--- /dev/null
+package genconfig2;
+
+use File::Basename;
+use strict;
+
+require tokenise;
+
+#
+
+# parser for control file
+
+# format:
+# type name (token) * {
+# ( match (params) *
+# ( {{ literal }} | ; )
+# )*
+# }
+# or
+# type name (token *) {{
+# literal
+# }}
+
+# tokens are separated by lwsp or ';'
+
+sub new {
+ my $class = shift;
+ my $options = shift;
+ my $self = {
+ options => $options,
+ objects => [],
+ };
+
+ foreach my $path (@_) {
+ loadControlFile($self, $path);
+ }
+
+ bless $self, $class;
+ return $self;
+}
+
+sub findInclude {
+ my $self = shift;
+ my $file = shift;
+
+ foreach my $dir (@{$self->{options}->{include}}) {
+ my $path = "$dir/$file";
+ return $path if -e $path;
+ }
+
+ return $file;
+}
+
+sub loadControlFile {
+ my $self = shift;
+ my $path = shift;
+ my $list = $self->{objects};
+ my $target;
+ my $item;
+ my $literal;
+ my $state = 0;
+ my @states;
+ my $tokeniser = new tokenise($path);
+
+ while (my $t = $tokeniser->next()) {
+ #print " $state $t\n";
+ if ($state == 0) {
+ if ($t eq 'include') {
+ my $file = $tokeniser->next();
+ $tokeniser->include(findInclude($self, $file));
+ } elsif ($tokeniser->{type} eq 'token') {
+ $target = { type => $t, options => [], items => [] };
+ push @$list, $target;
+ $state = 1;
+ } else {
+ die("$tokeniser->{file}->{path}:$tokeniser->{file}->{lineno}:$tokeniser->{colno}: expected type token");
+ }
+ } elsif ($state == 1) {
+ if ($tokeniser->{type} eq 'token') {
+ $target->{name} = $t;
+ $state = 2;
+ } else {
+ die("$tokeniser->{file}->{path}:$tokeniser->{file}->{lineno}:$tokeniser->{colno}: expected match token");
+ }
+ } elsif ($state == 2) {
+ if ($t eq '{') {
+ $state = 3;
+ } elsif ($tokeniser->{type} eq 'literal') {
+ $target->{literal} = stripLiteral($t);
+ $state =0;
+ } elsif ($tokeniser->{type} eq 'token') {
+ push @{$target->{options}}, $t;
+ } else {
+ die("$tokeniser->{file}->{path}:$tokeniser->{file}->{lineno}:$tokeniser->{colno}: expecting { or {{literal}} or option: not '$t'");
+ }
+ } elsif ($state == 3) {
+ if ($t eq '}') {
+ $state = 0;
+ } elsif ($tokeniser->{type} eq 'token') {
+ $item = { match => $t, options => [] };
+ push @{$target->{items}}, $item;
+ $state = 4;
+ } else {
+ die("$tokeniser->{file}->{path}:$tokeniser->{file}->{lineno}:$tokeniser->{colno}: expecting } or match token");
+ }
+ } elsif ($state == 4) {
+ if ($t eq ';') {
+ $state = 3;
+ } elsif ($tokeniser->{type} eq 'token') {
+ push @{$item->{options}}, $t;
+ } elsif ($tokeniser->{type} eq 'literal') {
+ $item->{literal} .= stripLiteral($t);
+ $state = 3;
+ } else {
+ die("$tokeniser->{file}->{path}:$tokeniser->{file}->{lineno}:$tokeniser->{colno}: not expecting type=$tokeniser->{type} value=$t");
+ }
+ }
+ }
+ die "parse error in '$path' state=$state" if $state;
+}
+
+sub stripLiteral {
+ my $t = shift;
+
+ if ($t =~ m/\n/s) {
+ $t =~ s/^\s*\n//s;
+ $t =~ s/\n\s+$/\n/s;
+ } else {
+ $t =~ s/^\s+//;
+ $t =~ s/\s+$//;
+ }
+ $t;
+}
+
+1;