Add temporary support for new config format.
authorNot Zed <notzed@gmail.com>
Mon, 31 Jan 2022 19:57:43 +0000 (06:27 +1030)
committerNot Zed <notzed@gmail.com>
Mon, 31 Jan 2022 20:08:52 +0000 (06:38 +1030)
src/export-defines
src/genconfig2.pm [new file with mode: 0644]

index 907b5c1..b32d5e8 100755 (executable)
@@ -1,11 +1,20 @@
 #!/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;
@@ -18,6 +27,10 @@ while (@ARGV) {
                $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;
        }
@@ -25,8 +38,20 @@ while (@ARGV) {
 
 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 = "";
@@ -166,14 +191,17 @@ END
        # 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");
diff --git a/src/genconfig2.pm b/src/genconfig2.pm
new file mode 100644 (file)
index 0000000..c3f7af1
--- /dev/null
@@ -0,0 +1,134 @@
+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;