From 60dba629ae7e0b2452e9b5d7a8b456f4cd2ca490 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Tue, 1 Feb 2022 06:27:43 +1030 Subject: [PATCH] Add temporary support for new config format. --- src/export-defines | 46 +++++++++++++--- src/genconfig2.pm | 134 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 src/genconfig2.pm diff --git a/src/export-defines b/src/export-defines index 907b5c1..b32d5e8 100755 --- a/src/export-defines +++ b/src/export-defines @@ -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 <%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 index 0000000..c3f7af1 --- /dev/null +++ b/src/genconfig2.pm @@ -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; -- 2.39.2