See the attached file. Save it anywhere, make it executable, that is all. I had to make some last minute changes, hopefully this didn't break the code which I didn't touch almost a year...
NOTE! I do not want to use any module/library, so it doesn't use File::Temp and simply assumes that the temp dir is "/tmp"; you can change $TMPDIR at the start if this is not correct on your system. fpp will create/remove a couple of __FPP__.* files in this directory. Currently it simply ignores import/library. If you want to put the FPP() code into some.lib, you will need to use fpp_import/fpp_export instead. IOW, import("file-with-FPP-code") won't work; fpp_import("file-with-FPP-code") or fpp_library("file-with-FPP-code") should (mostly) work. The search path for fpp_import/fpp_library is @INCDIR at the start of fpp, you should probably change it if you want to use fpp_import/fpp_library. Currently it blindly passes almost all options to /usr/bin/faust, so it will randomly fail if faust outputs anything but C/C++ code in scalar mode. Oleg.
#!/usr/bin/perl -w use strict; our $TMPDIR = '/tmp'; our @INCDIR = qw(/home/oleg/FAUST/LIB /home/oleg/FAUST/faust.git/libraries); #------------------------------------------------------------------------------ package re; our $bal_cur = '(?:\{(?:(?>[^\{\}]+)|(?-1))*\})'; our $bal_par = $bal_cur =~ tr/{}/()/r; our $bal_sqr = $bal_cur =~ tr/{}/[]/r; sub qr { my $r = join '',@_; qr/$r/; } sub list { join '|', map "(?:$_)", @_; } sub chop2($) { substr $_[0], +1,-1 } sub chop2s($) { &chop2 =~ s/^\s+|\s+$//gr } sub split_args(_) { my ($a, @a) = &chop2; push @a, $& =~ s/^\s+|\s+$//gr while $a =~ /(?: ($re::bal_par) | [^,])+/oxg; return @a; } #------------------------------------------------------------------------------ package perl::core; sub __z_expr($$) { $_[0] } sub __z_pure($$) { &pp_cpp::zmap =~ /^\w+\[[^]]+\]$/ ? 1 : 0 } sub __z_iota($$) { &pp_cpp::zmap =~ /\bIOTA\b/ ? 1 : 0 } sub __z_item($$$) { my ($vec, $len, $idx) = @_; $idx =~ s/^\(([+-]?\w+)\)$/$1/; my $expr = &pp_cpp::zmap || return $vec eq '0' || $idx eq '0' && $len eq '0' ? $vec : die "bad delay line: '$vec' [$idx]\n"; # my @inp = pp_cpp::inputs($expr); # warn "WARN! delay line '$vec' inputs: @inp\n" if @inp; $expr =~ /\[(\(\((?:dsp->)?IOTA\s*-\s*)?/g; my $full = $1 ? "$idx + $len - " : "$idx - $len + "; $expr =~ s/\G(\Q$len\E\b)?/defined $1 ? $idx : $full/er; } sub __l_len($) { 0 + &re::split_args } sub __l_item($$) { my @l = re::split_args (my $l = shift); @_ == 1 && $_[0] =~ /^\(?(\d+)\)?$/ && $1 < @l or die "bad list item: $l\[@_]\n"; $l[$1]; } sub __l_for(&$$$) { my ($l, $i, $v, $e) = @_; my @l = re::split_args $l; /\W/ and die "bad .for() arguments: ($i, $v, $e)\n" for $i, $v; my $re = qr/\b(?:($i)|($v))\b/; join '; ', map $e =~ s/$re/$1?$_:$l[$_]/egr, 0..$#l; } #------------------------------------------------------------------------------ package pp_dsp; our (%GLOB, %INST); sub expand_perl; sub expand_perl { $_[0] =~ s/\$\.(\w+)($re::bal_par)/ my $f = can perl::core:: $1 or die "undefined perl func: $1$2\n"; ord '$' == ord prototype $f ? $f->(re::split_args expand_perl $2) : expand_perl $f->(re::split_args $2) /oegr; } sub __expand_fpp { my ($this, $code, $args) = @_; my ($name, $uniq) = 0+$code; sub expand; local *expand = sub { my ($once, $dict, $uarg) = shift; if ($code->{uarg}) { while (my ($n, $a) = each %{$code->{uarg}}) { next if $args->[$n] eq $a; die "can't rebind arg_$n from '$a' to '$args->[$n]'\n"; } } if ($once) { $uniq = $once->{'$'} ||= {}; $code = $once->{$name}, return $this if $once->{$name}; } $this->{$_} .= expand_perl +($code->{$_}//next) =~ s{\$(\w+)\b}{ my $n = $1; $dict->{$n} ||= ($n =~ /\D/) ? ("$n\__" . ++($uniq->{$n}||='00')) : ($uarg->{$n} = $args->[$n] // die) }egr for @_; if ($once) { $code = $once->{$name} = {%$code}; $code->{uarg} = $uarg if $uarg; delete @{$code}{@_}; if (my $vars = re::list keys %$dict) { ref or s/\$($vars)\b/$dict->{$1}/g for values %$code; } } $this; }; expand \%GLOB, qw(FILE); expand \%INST, qw(DECL INIT LOOP POST); expand undef, qw(file decl init loop post exec); } sub expand_fpp { my ($func, $args) = @_; my ($code, $this) = ($func->{code}, {}); if ($func->{deps} && !$INST{0+$code}) { __expand_fpp $this, $_ for @{$func->{deps}}; } shift @$args if exists $func->{arg0}; __expand_fpp $this, $code, $args; } my (%STRN, %FUNC, %DEPS); sub fix_strn(_) { defined (wantarray) ? $_[0] =~ s/\STRN!(\d+)\b/$STRN{$1}||die/egr : $_[0] =~ s/\STRN!(\d+)\b/$STRN{$1}||die/eg; } sub mk_eval($$) { mk_ffunc(0,$_[0],'_int_',{eval => undef, code => {exec=>$_[1]}}); } sub mk_ffunc { my ($pure, $narg, $type, $func) = @_; $func = {code => {exec => $func}} unless ref $func; if ($type =~ /^_(int|float)_$/) { $type = $1 } else { $func->{type} = $type; $type = $type =~ /^(?:float|(?:(?:long\s+)?double)|quad)$/ ? 'float' : 'int'; } my $arg0 = ''; if (0) { } elsif (!$pure && $narg) { CORE::state $kSamp; $arg0 = $kSamp ||= mk_eval 0, 'BUG'; } elsif ($pure && !$narg) { $arg0 = '0'; } if ($arg0 ne '') { $narg++; $func->{arg0} = undef; $arg0 = "($arg0)"; } CORE::state $uniq = '000'; my $name = 'fpp_func_' . ++$uniq; $FUNC{$name} = $func; my $args = join ',', qw(float) x $narg; qq{ffunction($type $name($args),"","")$arg0} } sub push_fpp_bus { CORE::state $done; return if $done++; my $b0 = mk_eval 0, ''; my $b1 = mk_eval 1, '$0'; my $b2 = mk_eval 2, '$0,$1'; print main::FAUST "// ======== <push>\n", "_fpp_bus_(0) = $b0; _fpp_bus_(1) = $b1;\n", "_fpp_bus_(n) = _, _fpp_bus_(n-1) : $b2;\n"; } sub expand_args { my ($argn, $argz, $argl) = @_; my $re_argn = join '|', keys %$argn; while (/\$($re_argn)\b/g) { my ($arg, $pos) = ($1, pos() - 1 - length $1); my ($out, $type, $func, @args) = '$'.$argn->{$arg}; if (defined(my $z = $argz->{$arg})) { ($func, $type, @args) = ('__z_', 'dline', $out,$z); if (/\G\s*($re::bal_sqr)/gc) { ($func, $type) = '__z_item'; my $i = re::chop2s $1; push @args, "($i)"; } } elsif (exists $argl->{$arg}) { @args = "($out)"; if (/\G\s*($re::bal_cur)/gc) { $func = '__l_item'; my $i = re::chop2s $1; push @args, "($i)"; } elsif (/\G\s*\./) { ($func, $type) = ('__l_', 'flist'); } } if ($type) { my $err = '$'.$arg; /\G\s*\.\s*(\w+)/gc or die "bad usage of $type arg: '$err'\n"; $func .= $1; $err .= $&; my $args = length prototype (can perl::core:: $func or die "bad $type op: '$err'\n"); if ($args -= @args) { /\G\s*($re::bal_par)/gc or die "bad usage of $type op: '$err'\n"; push @args, re::chop2 $1; $err .= $&; $args == re::split_args $1 or die "bad $type op argc: '$err'\n"; } } $out = "\$.$func(${\join',',@args})" if $func; substr $_, $pos, pos() - $pos, $out; pos = $pos; } } sub parse_args { my $lambd; my (%argn, %argz, %argl); my (@args, @pass, @with); s/^\s*($re::bal_par)//o or die "arglist"; for (re::split_args $1) { my ($with, $argn,$argv, $m,$z,$l) = s/^=\s*//; s/^(?=\D)(\w+)\s*// or die "bad arg: '$_'"; exists $argn{$argn = $argv = $1} and die "dup arg: '$1'"; if (s/\s*(?:($re::bal_sqr)|($re::bal_cur))$//) { $1 ? ($z = re::chop2s $1) : ($l = re::chop2s $2); $m = s/\s*:$//; } if (!$with and $with = s/^=\s*//) { push @with, "$argn=$_; "; } elsif ($m ||= ord $_ == ord ':') { $argv = "($argn$_)"; } elsif (length) { die "bad arg '$argn' modifier: '$_'"; } if (defined $z) { $argv = "$argv@(int($z))" if $z; $argz{$argn} = $z =~ /\D/ ? '$'.(-1 + push @pass, "int($z)") : ($z || 0); } elsif (defined $l) { push_fpp_bus; $argl{$argn} = undef; my ($n, $a) = ("outputs($argv)", ", $argv"); if (length $l) { $n = "int($l)"; $a = '', $with = 1 unless $with || $m; } $argv = "_fpp_bus_($n$a)"; } $argn{$argn} = @pass; push @pass, $argv; if (!$with) { push @args, $argn; $lambd ||= $m || $z || defined $l; } } if ($lambd || @pass > @args) { $lambd = join ',', @args; $lambd = "\\($lambd)." if $lambd; $lambd .= '(' . join ',', @pass; $lambd .= " with { @with}" if @with; } 0+@pass, $lambd, %argn && sub { expand_args \%argn, \%argz, \%argl; }; } sub parse_block { my ($zone, $re_z, $earg) = @_; $_[1] = $re_z = qr/(.*?)(?:\b($re_z):|$)/s unless ref $re_z; s/^\s*($re::bal_cur)//o or die "body"; local $_ = re::chop2 $1; /\$\s*[\W\d]\w*/x and die "bad sigil var: '$&'\n"; &$earg() if $earg; for (my $code;;) { /$re_z/g; my ($c, $z) = ($1, $2); for ($c) { /\S/ or last; s/^\s*$//mg; s/^\n+//; s/\s*$/\n/; s/^(\s*)// and s/^$1//mg; $code->{$zone} .= $_; } $zone = $z || return $code; } } sub parse_fpp { my ($narg, $lambd, $earg) = parse_args; my $func; if (s/^\s*\[//) { s/(^.*)?\]// or die 'deps list'; $func->{deps} = [map { /^\s*(?=\D)(\w+)\s*$/ or die "bad dep name: $_"; $DEPS{$1} || die "bad dep: $_"; } split ',', $1]; } my $pure = s/^\s*pure\b//; $func->{eval} = undef if s/^\s*eval\b//; my @type; @type = map s/^\s+|\s+$//gr, split ',', $1 if s/^\s*(?=\S)([^\{]+)//; CORE::state $re_zone = 'FILE|DECL|_INIT|INIT|file|decl|_init|init|LOOP|loop|POST|post|exec'; my $code = parse_block 'exec', $re_zone, $earg; s/\s+/ /g, s/\s*;*\s*$/;/ for $code->{exec} // die 'no exec'; my ($type, $tuple); if (@type <= 1) { $type = $type[0] // '_float_'; } else { CORE::state $uniq = '000'; $type = 'struct fpp_tuple_' . ++$uniq; $code->{exec} =~ s/([^;]+);$/ ($type){$1 };/ or die; my $sdef = join ' ', map "$type[$_] m_$_;", 0..$#type; # OK, this is ugly, but lets do this here for now ... $sdef =~ s/\b_int_\b/int/g; $sdef =~ s/\b_float_\b/$pp_cpp::O_FLOAT/g; $code->{FILE} .= "$type { $sdef };\n"; $tuple = join ',', map { mk_ffunc 0, 1, $type[$_], "((($type)\$0).m_$_)"; } 0..$#type; } $func->{code} = $code; exists $func->{eval} ? ($code->{exec} =~ s/\s*;$//) : ($code->{exec} = "({ $code->{exec} })"); my $ffunc = mk_ffunc $pure, $narg, $type, $func; $ffunc = "$lambd : $ffunc)" if $lambd; $ffunc = "($ffunc <: $tuple)" if $tuple; $ffunc; } sub parse_dep { s/^\s*\(\s*(\w*)\s*\)// or die 'dep name'; my $name = $1; CORE::state $re_zone = 'FILE|DECL|_INIT|INIT|LOOP|POST'; my $code = parse_block 'FILE', $re_zone; if ($name) { die 'redefined' if $DEPS{$name}; $DEPS{$name} = $code; } else { $DEPS{''}{$_} .= $code->{$_} for keys %$code; } s/^\s*;// ? '' : die 'expected ;'; } sub parse_dsp { our $REGERROR; s{ (" (*:string) (?:\\.|[^"])* (*SKIP) ") | (?: \/\* (*:comment) (?:[^\*]+|\*(?!\/))* (*SKIP) \*\/) | (?: \/\/ [^\n]*) }{ if (defined $1) { CORE::state $uniq = '000'; $STRN{++$uniq} = $1; 'STRN!' . $uniq; } }xegs; die "unterminated $REGERROR" if $REGERROR && $REGERROR ne 1; s/(?:\h*\n){3,}/\n\n/g; # unneeded s{ \b (?:fpp_)(?:(import)|(library)) \b (?: \s*\(\s* STRN!(\d+) \s*\)\s* (?(1);) )? }{ my $n = $3 && $STRN{$3} // do { /\G([^\n]*)/; die "syntax error: '$1'"; }; main::parse_file(re::chop2 $n, !$1); }xeg; my $dsp = ''; while (m{ \b (?: __FPP (?{\&parse_dep}) | FPP (?{\&parse_fpp}) ) \b }xo) { substr $_, 0, length($`) + length($&), ''; $dsp .= fix_strn $`; $dsp .= $^R->(); } $dsp . fix_strn; } #------------------------------------------------------------------------------ package pp_cpp; our ($O_FLOAT) = 'float'; my $THIS = 'dsp'; my $TYPE = '(?: int | float | double | quad)'; sub re_call { my $f = &re::list; "\\b($f)\\s*($re::bal_par)"; } sub re_this { my $t = &re::list; "\\b(?:$THIS->)?($t)\\b"; } sub re_cast { my $expr = "($_[0])"; my $cast = re::list "\\b $TYPE \\( $expr \\)", "\\( $TYPE \\)+ $expr"; qr/(?| $cast )/x; } our (%ZMAP, $FILE, $DECL, $INIT, $EXEC); sub uncast_one { CORE::state $cast = re_cast '.*'; 1 while s/\A\s* $cast \s*\z/$1/oxg; } sub uncast_all { my $cast = re_cast $_[0]; for ($INIT, $EXEC) { 1 while s/$cast/$1/g; } } sub fix_types { my $funcs = shift; my $ftype; while (my ($n, $f) = each %$funcs) { $ftype->{$n} = exists $f->{eval} ? undef : $f->{type} // next } uncast_all my $calls = re_call keys %{$ftype || return}; my (%vtype, @voids); for ($INIT, $EXEC) { $vtype{$1} = $ftype->{$2} // do { push @voids, $1; 'void'; } while /\b (\w+) \s*=\s* $calls/xg; } %vtype or return; uncast_all my $vtype = re_this keys %vtype; s/\b $TYPE \s+ $vtype/$vtype{$1} $1/xg for $DECL, $EXEC; s/\h* $vtype \s* = \s* 0; \h*\n?//xg # TempPerm, ocpp only for $INIT; @voids or return; my $voids = re_this @voids; s/\h* void \s+ $voids \s*; \h*\n?//xg for $DECL, $EXEC; for ($INIT, $EXEC) { s/$voids (?! \s*= )/_($1)/xg; s/\h* (?:void\s+)? $voids \s*=\s* ([^;]+) \s*; \h*\n? /_($1,($2))/xg; } } sub mark_block($$_) { $_[2] =~ s/(?<=\{)(?=(\n\h*)\S)/$1#MARK $_[0]/ or die; my $ind = $1; $_[2] =~ s/(?=\n\h*\}$)/$ind#MARK $_[1]/ or die; } sub add_marks { $DECL =~ s/^(?=(\h*)\S)/$1#MARK CALL\n/m or die; mark_block 'CALL', 'EXIT' for $INIT, $EXEC; $EXEC =~ s/(\n\h*) (for \s* ($re::bal_par) \s*) ($re::bal_cur)/ my ($ind, $for, $block) = ($1,$2,$4); mark_block 'LOOP', 'POST', $block; $ind . "#MARK _CALL" . $ind . $for . $block . $ind . "#MARK _EXIT"; /oex or die; fill_mark($EXEC, $_, '') for qw(CALL EXIT _CALL _EXIT); } sub fill_mark { my (undef, $mark, $code) = @_; $code .= "\n" if $code ne ''; $_[0] =~ s/^(\h*)#MARK $mark\n/ my $i = $1; $code =~ s|^(?=\h*\S)|$i|mgr; /me or die; } sub expand_all { my ($extra, $funcs) = @_; my %voids; sub expand_void; local *expand_void = sub { return $voids{$_[0]} // die if @_==1; $voids{$_[0]} = re::chop2 $_[1]; ''; }; my @extra = $extra; sub expand_func; local *expand_func = sub { my ($name, $args) = @_; s/\.0[fL]$// for @$args; my $this = pp_dsp::expand_fpp $funcs->{$name}, $args; # s/THIS/ for values %$this; push @extra, $this if 1 < keys %$this; return delete $this->{exec}; }; my $calls = re::qr re_call '_', keys %$funcs; sub expand_code; local *expand_code = sub { s/$calls/ my ($f, @a) = ($1, re::split_args $2); uncast_one, expand_code for @a; $f eq '_' ? expand_void @a : expand_func $f,\@a; /xge; }; expand_code for $INIT, $EXEC; sub collect; local *collect = sub { join '', grep defined, map @$_{@_}, @extra; }; add_marks; $FILE .= collect qw(FILE file); $FILE .= "\n" if $FILE ne "\n"; fill_mark $DECL, 'CALL', collect qw(DECL decl); fill_mark $INIT, 'CALL', collect qw(_INIT _init); fill_mark $INIT, 'EXIT', collect qw(INIT init); fill_mark $EXEC, 'LOOP', collect qw(LOOP loop); fill_mark $EXEC, 'POST', collect qw(POST post); } sub read_cpp { my ($fd, %items) = @_; my ($is_c, $class, @code); local $_; sub getl; local *getl = sub { push @code, $_ if defined; defined ($_ = <$fd>); }; sub mark; local *mark = sub { push @code, $_ unless defined $_[1]; push @code, $_[1]; *{delete $items{$_[0]}} = \$code[-1]; undef $_; }; while (getl) { unless ($class) { ($class) = /^\s*\#define \s* FAUSTCLASS \s+(\w+)\s*$/x; } elsif (/^\s*$/) { mark -file, $_; } elsif (/^\s*typedef \s+ struct \s* \{ \s*$/x) { $is_c = 1; last; } elsif (/^\s*class \s+ $class \s*:\s* public \s+ (?:\w+) \s*\{\s*$/x) { $is_c = 0; while (getl) { last if /^\s* private: \s*$/x } last; } } eof and die "can't find the start of dsp declaration"; mark -decl; while (<$fd>) { last if $is_c ? m/^\s* \} \s* $class \s*; \s*$/x : m/^\s* public: \s*$/x; $code[-1] .= $_; } eof and die "can't find the end of dsp declaration"; %items = map {$_.$class, $items{$_}} keys %items if $is_c; my $calls = re_call keys %items; while (getl) { # temporary hack if (/^(\s*)instanceConstants\(/) { (my $i, $_) = $_; 1 while getl && !/^\s*instanceClear/; $_ .= $i; next; } my ($prot, $func, undef, $body) = /^(.*? \b void \s+ $calls \s*) (\{ \s*\z)/x or next; $items{$func} or die "redefenition of $func()"; while (<$fd>) { $body .= $_; next unless /^\s* \} \s*$/x; last if $body =~ /^($re::bal_cur)\s*\z/o; } eof and die "can't find the end of $func()"; mark $func, $prot.$body; } die "can't find funcs: ", join(',', map "$_()", keys %items) if %items; \@code; } # ---------------------------------------------------------------------------- my $ZVEC = '(?:\b(?:$THIS->)?[if][VR]ec\d+\b)'; my $TEMP = '(?:\b[if]Temp\d+\b)'; sub inputs { my %seen; grep defined && !$seen{$_}++, $_[0] =~ /\b(?: (?:$TYPE) | (?:$THIS) | (?:IOTA) | (?:[if]Const\d+) | (?: (?:input|[if][VR]ec)\d+\b) | ((?=\D)\w+ (?! \(\s*[^\)] )) )\b/oxg } sub __zmap($) { my $v = $_[0]; # 1==(() = ($v =~ /$ZVEC/og)) return $v if $v =~ /\b$ZVEC/og ? $v !~ //g : do { my ($c, $t) = 0; $v =~ s{($TEMP)}{defined($t = $ZMAP{$1}) ? (++$c, $t) : $1}oeg; $c == 1; }; } sub build_zmap { for (split /(?:\h*;)?\n/, $EXEC) { my ($l, $r) = /(.*\S) \s*=\s* (.*)/x or next; if (my ($t) = $l =~ /($TEMP)$/o) { $ZMAP{$t} = __zmap $r || next; } elsif (my ($v, $i) = $l =~ /($ZVEC)\[([^\]]+)\]$/o) { $i eq 0 || $i =~ s/\bIOTA\b/(IOTA - 0)/ or next; $ZMAP{$r} = $v."[$i]"; } } } sub zmap($) { my $expr = $_[0]; $ZMAP{$expr} //= __zmap $expr; } # ---------------------------------------------------------------------------- sub opt_const { # TODO: can make $DECL empty, add_marks(DECL) will die. # move the callsite somewhere else but after fix_type() # which can remove a "void" var we can opt otherwise. my $freq = $_[1] ? '' : 'fSamplingFreq'; my @temp = grep { $EXEC !~ /\b$_\b/ and $_ ne $freq } $DECL =~ /\b$TYPE\s+(\w+);/oxg or return; my $decl = ''; my $temp = re::list @temp; $DECL =~ s/\h*($TYPE\s+($temp);\h*\n)/$decl .= $1; ''/xeg; $INIT =~ s/\b$THIS->($temp)\b/$1/xg; #if $IS_C substr +($_[0]->{_INIT} //= ''),0,0, $decl."\n"; } sub do_cpp { my ($fd, $extra, $funcs) = @_; my $code = read_cpp $fd, -file => \*FILE, -decl => \*DECL, instanceConstants => \*INIT, compute => \*EXEC; build_zmap; fix_types $funcs; opt_const $extra, 0; expand_all $extra, $funcs; pp_dsp::fix_strn for $FILE, $INIT, $EXEC; $code; } #------------------------------------------------------------------------------ package main; sub slurp_file { my ($name, $idir) = @_; my $path; if (!$idir || $name =~ /^\.{0,2}\//) { $path = $name if -f $name; } else { for (@$idir) { my $n = "$_/$name"; $path = $n, last if -f $n; } } $path // die "can't find file '$name'"; open my $fd, '<', $path or die "can't open file '$path': $!"; local $/; <$fd>; } sub parse_file { my ($name, $islib) = @_; my ($isinc, $env) = defined $islib; local $_; if (defined $name) { CORE::state %cache; CORE::state $uniq = '00'; # import() after library() can't work anyway, but let's # check $islib and return ''; this allows import(stdfaust) # which does library(all) which in turn imports everything. return $islib && $cache{$name} if exists $cache{$name}; $env = $cache{$name} = $islib && 'FPP_ENV_' . ++$uniq; $_ = slurp_file $name, $isinc && \@INCDIR; } else { warn "reading from stdin ...\n" if -t STDIN; $_ = do { local $/; <STDIN> }; $name = '<stdin>'; } my $dsp = pp_dsp::parse_dsp; print FAUST "\n" if tell FAUST; print FAUST '// ======== ', $isinc?'INCLUDE: ':'CMDLINE: ', $name, "\n"; print FAUST $env, " = environment {\n" if $islib; print FAUST $dsp; print FAUST "};\n" if $islib; $env; } sub usage { die "fpp: usage\n"; } my @TMPF; END { unlink @TMPF } sub main { my ($faust, $fmt, $ktf, @opt, @inp, $out) = 'faust'; while (defined($_ = shift)) { if (ord != ord '-') { push @inp, $_; next; } elsif ($_ eq '-k') { $ktf = 1; next; } elsif ($_ eq '-fmt') { $fmt = shift // usage; next; } elsif ($_ eq '-faust') { $faust = shift // usage; next; } elsif ($_ eq '-o') { $out = shift // usage; next; } elsif (/^-(double|quad)$/) { $O_FLOAT = $1; } push @opt, $_; push @opt, shift // usage if /^ -mdlang | --mathdoc-lang | -f | --fold | -mns | --max-name-size | -mcd | --max-copy-delay | -a | -cn | --class-name | -scn | --super-class-name | -pn | --process-name | -t | --timeout | -vs | --vec-size | -lv | --loop-variant | -lang | --language | -A | --architecture-dir | -I | --import-dir | -L | --library | -O | --output-dir | -inj | --inject | -fm | --fast-math $/x; } -d -w $TMPDIR or die "ERR!! bad \$TMPDIR '$TMPDIR': $!\n"; my ($dsp, $cpp) = map "$TMPDIR/__FPP__.$_", qw(dsp cpp); push @TMPF, $dsp, $cpp unless $ktf; open FAUST, '>', $dsp or die "ERR!! can't open '$dsp': $!\n"; do { parse_file shift @inp} while @inp; close FAUST; unlink $cpp; system $faust, @opt, $dsp, '-o', $cpp and die "\n"; open my$fd, '<', $cpp or die "ERR!! can't open '$cpp': $!\n"; my $code = pp_cpp::do_cpp $fd, $DEPS{''}, \%FUNC; open STDOUT,'>', $out or die "ERR!! can't open '$out': $!\n" if defined $out; if (defined $fmt) { $fmt eq 0 or usage; print $FILE, $DECL, $INIT, $EXEC; } else { print @$code; } } main @ARGV;
_______________________________________________ Faudiostream-users mailing list Faudiostream-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/faudiostream-users