use strict; use warnings; package Clownfish::Binding::Core::File; use Clownfish::Util qw( a_isa_b verify_args ); use Clownfish::Binding::Core::Class; use File::Spec::Functions qw( catfile splitpath ); use File::Path qw( mkpath ); use Scalar::Util qw( blessed ); use Fcntl; use Carp; my %write_h_PARAMS = ( file => undef, dest => undef, header => undef, footer => undef, ); sub write_h { my ( undef, %args ) = @_; verify_args( \%write_h_PARAMS, %args ) or confess $@; my $file = $args{file}; confess("Not a Clownfish::File") unless a_isa_b( $file, "Clownfish::File" ); my $h_path = $file->h_path( $args{dest} ); # Unlink then open file. my ( undef, $out_dir, undef ) = splitpath($h_path); mkpath $out_dir unless -d $out_dir; confess("Can't make dir '$out_dir'") unless -d $out_dir; unlink $h_path; sysopen( my $fh, $h_path, O_CREAT | O_EXCL | O_WRONLY ) or confess("Can't open '$h_path' for writing"); # Create the include-guard strings. my $include_guard_start = $file->guard_start; my $include_guard_close = $file->guard_close; # Aggregate block content. my $content = ""; for my $block ( $file->blocks ) { if ( a_isa_b( $block, 'Clownfish::Parcel' ) ) { } elsif ( a_isa_b( $block, 'Clownfish::Class' ) ) { my $class_binding = Clownfish::Binding::Core::Class->new( client => $block, ); $content .= $class_binding->to_c_header . "\n"; } elsif ( a_isa_b( $block, 'Clownfish::CBlock' ) ) { $content .= $block->get_contents . "\n"; } else { confess("Invalid block: $block"); } } print $fh < undef, dest => undef, header => undef, footer => undef, ); sub write_c { my ( undef, %args ) = @_; verify_args( \%write_h_PARAMS, %args ) or confess $@; my $file = $args{file}; confess("Not a Clownfish::File") unless a_isa_b( $file, "Clownfish::File" ); my $c_path = $file->c_path( $args{dest} ); # Unlink then open file. my ( undef, $out_dir, undef ) = splitpath($c_path); mkpath $out_dir unless -d $out_dir; confess("Can't make dir '$out_dir'") unless -d $out_dir; unlink $c_path; sysopen( my $fh, $c_path, O_CREAT | O_EXCL | O_WRONLY ) or confess("Can't open '$c_path' for writing"); # Aggregate content. my $content = ""; my $c_file_syms = ""; for my $block ( $file->blocks ) { if ( blessed($block) ) { if ( $block->isa('Clownfish::Class') ) { my $bound = Clownfish::Binding::Core::Class->new( client => $block, ); $content .= $bound->to_c . "\n"; my $c_file_sym = "C_" . uc( $block->full_struct_sym ); $c_file_syms .= "#define $c_file_sym\n"; } } } print $fh <write_c( file => $file, # required dest => '/path/to/autogen_dir', # required header => "/* Autogenerated file. */\n", # required footer => $copyfoot, # required ); Generate a C header file containing all class declarations and literal C blocks. =over =item * B - A L. =item * B - The directory under which autogenerated files are being written. =item * B
- Text which will be prepended to each generated C file -- typically, an "autogenerated file" warning. =item * B