Syntax change for 'include x' -> '%include x;'
authorNot Zed <notzed@gmail.com>
Wed, 23 Mar 2022 21:02:26 +0000 (07:32 +1030)
committerNot Zed <notzed@gmail.com>
Wed, 23 Mar 2022 21:02:26 +0000 (07:32 +1030)
Allow perl modules to be included in .api files.
Allow matching names by perl module function.

src/notzed.apiobject/gen/apiobject.api
src/notzed.apistatic/gen/apistatic.api
src/notzed.clstatic/gen/opencl.api
src/notzed.ffmpeg/gen/ffmpeg.api
src/notzed.nativez/bin/export-api
src/notzed.nativez/bin/generate-api
src/notzed.nativez/lib/api.pm
src/notzed.nativez/lib/config.pm

index 408166b..a75f98f 100644 (file)
@@ -2,8 +2,8 @@
 
 # maps functions to objects
 
-include types.api
-include code.api
+%include types.api;
+%include code.api;
 
 struct <default> default=all field:rename=studly-caps access=rw {
 }
index da1fff8..7e1ed24 100644 (file)
@@ -3,8 +3,8 @@
 # example of a simple 'static' library with all functions
 # and constants in one class and no special handling
 
-include types.api
-include code.api
+%include types.api;
+%include code.api;
 
 # collect all functions and constants into one object
 library APILib load=api {
index 3157e91..3bad336 100644 (file)
@@ -1,6 +1,6 @@
 # -*- Mode:text; tab-width:4; electric-indent-mode: nil; indent-line-function:insert-tab; -*-
 
-include code.api
+%include code.api;
 
 # override cl_event entirely
 type /^u64:u64:\$\{_cl_event\}$/ copy=<pointer> {
@@ -8,7 +8,7 @@ type /^u64:u64:\$\{_cl_event\}$/ copy=<pointer> {
        tonative        {{ 'cl_event_list.address({value})' }}
 }
 
-include types.api
+%include types.api;
 
 struct <default> struct:rename=s/^_cl_/cl_/ {
 }
index a003ecb..0d7dd84 100644 (file)
@@ -1,7 +1,7 @@
 # -*- Mode:text; tab-width:4; electric-indent-mode: nil; indent-line-function:insert-tab; -*-
 
-include code.api
-include types.api
+%include code.api;
+%include types.api;
 
 struct <default> field:rename=studly-caps default=all func:rename=camel-case access=rw {
 }
index 6fcbf02..6ecd12d 100755 (executable)
@@ -102,6 +102,7 @@ if ($mode eq 'make-rule') {
 
        push @list, $apidef;
        push @list, map { abs2rel($_) } @{$api->{includes}};
+       push @list, map { dirname($apidef)."/$_->[1]" } grep { $_->[0] eq '%require' } @{$api->{pragmas}};
 
        if (defined $var->{'make-file'}) {
                open (my $f, ">", $var->{'make-file'}.'~') || die "writing $var->{'make-file'}";
index 9d6a74f..f0fee75 100755 (executable)
@@ -56,6 +56,7 @@ while (@ARGV) {
 }
 
 push @{$vars->{include}}, "$FindBin::Bin/../lib";
+push @INC, dirname($apidef);
 
 print Dumper($vars) if $vars->{verbose};
 
@@ -122,7 +123,7 @@ sub formatItems {
        @list = grep {
                $api->{output}->{"$_->{type}:$_->{name}"}++;
                $res->{seen}->{"$_->{type}:$_->{name}"}++ == 0
-       } $api->findMatches($inc);
+       } $api->findMatches($inc, $res->{ctx});
 
        if ($inc->{type} eq 'func') {
                my $def = $api->{index}->{'func:<default>'};
@@ -234,6 +235,7 @@ sub formatStruct {
        } @membersOutput;
 
        my $res = {
+               ctx => $s,
                library => [],
                func => [],
                define => [],
@@ -279,6 +281,7 @@ sub exportLibraries {
 
                my $library = findTemplateName($api, api::optionValue('template', 'code:class=library', $obj, $def));
                my $res = {
+                       ctx => $obj,
                        library => [],
                        func => [],
                        init => [],
@@ -335,7 +338,7 @@ sub exportStructs {
 
        # first those directly referenced
        foreach my $obj (grep { $_->{type} =~ m/call|struct|union/ } @{$api->{api}}) {
-               my @list = $api->findMatches($obj);
+               my @list = $api->findMatches($obj, $obj);
 
                print "gen ".($#list+1)." $obj->{type} $obj->{name}\n" if ($api->{vars}->{verbose} > 0);
                foreach my $s (@list) {
index ec07956..636bb41 100644 (file)
@@ -96,6 +96,12 @@ sub new {
                $self->{data} = { %{$self->{data}}, %{$info} };
        }
 
+       foreach my $p (@{$conf->{pragmas}}) {
+               if ($p->[0] eq '%require') {
+                       require $p->[1];
+               }
+       }
+
        analyseAPI($self);
        preprocess($self);
 
@@ -397,15 +403,26 @@ sub addDependencies {
 sub findMatches {
        my $api = shift;
        my $inc = shift;
+       my $ctx = shift;
        my $data = $api->{data};
 
-       if ($inc->{match} eq 'func:<match-function>') {
-               my $match = eval $inc->{literal};
+       if ($inc->{match} eq 'func:<matcher>') {
+               # or just last option?
+               my $code;
+
+               if (defined($inc->{literal})) {
+                       $code = 'sub { '.$inc->{literal}.' }';
+               } else {
+                       my @options = @{$inc->{options}};
+                       $code = 'sub { '.$options[$#options].'(@_) }';
+               }
+
+               my $match = eval $code;
 
                if (!defined($match)) {
                        die "unable to parse match function $inc->{match} $! $@";
                }
-               grep { $match->($_) } values %$data;
+               grep { $match->($_, $ctx) } grep { $_->{type} eq $inc->{type} } values %$data;
        } else {
                my $s = $data->{$inc->{match}};
 
@@ -432,7 +449,7 @@ sub findDependencies {
                                next if ($inc->{type} eq 'library');
 
                                #print "? $inc->{regex}\n";
-                               foreach my $s (findMatches($api, $inc)) {
+                               foreach my $s (findMatches($api, $inc, $obj)) {
                                        my $n = "$s->{type}:$s->{name}";
 
                                        print "+ $n\n";
@@ -444,7 +461,7 @@ sub findDependencies {
                        }
                } elsif ($obj->{type} =~ m/^(struct|union|call|func|enum|define)$/) {
                        #foreach my $n (grep { $_ =~ m/$obj->{regex}/ } keys %data) {
-                       foreach my $s (findMatches($api, $obj)) {
+                       foreach my $s (findMatches($api, $obj, $obj)) {
                                my $n = "$s->{type}:$s->{name}";
 
                                $seen{$n}++;
@@ -881,7 +898,7 @@ sub processType {
 
                # handle other types included/mark them no-output
                $seen->{"$s->{type}:$s->{name}"} = 0;
-               processLibrary($api, $seen, $obj);
+               processLibrary($api, $seen, $obj, $s);
        }
 
 }
@@ -890,6 +907,7 @@ sub processLibrary {
        my $api = shift;
        my $seen = shift;
        my $lib = shift;
+       my $ctx = shift;
        my $data = $api->{data};
 
        return if ($seen->{"$lib->{type}:$lib->{name}"}++);
@@ -904,7 +922,7 @@ sub processLibrary {
                print " $inc->{match}\n" if ($api->{vars}->{verbose} > 1);
 
                if ($inc->{type} =~ m/func|call/on) {
-                       my @list = findMatches($api, $inc);
+                       my @list = findMatches($api, $inc, $ctx);
 
                        #print 'inc='.Dumper($inc);
                        #print "match $inc->{regex} .options=".Dumper($inc->{options});
@@ -921,11 +939,11 @@ sub processLibrary {
                        foreach my $l (grep { "$_->{type}:$_->{name}" =~ m/$inc->{regex}/ } @{$api->{api}}) {
                                # included libraries are never output directly
                                $l->{output} = 0;
-                               processLibrary($api, $seen, $l);
+                               processLibrary($api, $seen, $l, $ctx);
                        }
                } elsif ($inc->{type} =~ m/define|enum/on) {
                        # suppress direct output of anything included
-                       foreach my $c (findMatches($api, $inc)) {
+                       foreach my $c (findMatches($api, $inc, $ctx)) {
                                $c->{output} = 0;
                        }
                }
@@ -939,7 +957,7 @@ sub postprocess {
 
        # apply requested options to specific objects (not defaults)
        foreach my $obj (grep {$_->{type} =~ m/^(func|call|struct|union)$/} @{$api->{api}}) {
-               my @list = findMatches($api, $obj);
+               my @list = findMatches($api, $obj, $obj);
 
                if ($obj->{type} =~ m/func|call/) {
                        processTypeFunc($api, $seen, $obj, @list);
@@ -952,7 +970,7 @@ sub postprocess {
        foreach my $lib (grep {$_->{type} eq 'library'} @{$api->{api}}) {
                next if defined($lib->{output});
                $lib->{output} = 1;
-               processLibrary($api, $seen, $lib);
+               processLibrary($api, $seen, $lib, $lib);
        }
 
        # apply options for default object types
index 7dd8a91..3b4cdff 100644 (file)
@@ -29,6 +29,7 @@ sub new {
                options => $options,
                objects => [],
                includes => [],
+               pragmas => [],
        };
 
        foreach my $path (@_) {
@@ -65,11 +66,25 @@ sub loadControlFile {
        while (my $t = $tokeniser->next()) {
                #print " $state $t\n";
                if ($state == 0) {
-                       if ($t eq 'include') {
-                               my $file = findInclude($self, $tokeniser->next());
+                       if ($t =~ m/^%/) {
+                               my @pragma = ( $t );
+                               my $a = $tokeniser->next();
 
-                               push @{$self->{includes}}, $file;
-                               $tokeniser->include($file);
+                               while (defined($a) && $a ne ';') {
+                                       push @pragma, $a;
+                                       $a = $tokeniser->next();
+                               }
+
+                               if ($t eq '%include') {
+                                       my $file = findInclude($self, $pragma[1]);
+
+                                       print "including $file\n";
+
+                                       push @{$self->{includes}}, $file;
+                                       $tokeniser->include($file);
+                               } else {
+                                       push @{$self->{pragmas}}, \@pragma;
+                               }
                        } elsif ($tokeniser->{type} eq 'token') {
                                $target = { type => $t, options => [], items => [] };
                                push @$list, $target;