summaryrefslogtreecommitdiff
path: root/ext/xsubpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/xsubpp')
-rwxr-xr-xext/xsubpp196
1 files changed, 150 insertions, 46 deletions
diff --git a/ext/xsubpp b/ext/xsubpp
index bb6972008b..1e13118ad5 100755
--- a/ext/xsubpp
+++ b/ext/xsubpp
@@ -1,11 +1,13 @@
#!./miniperl
+'di ';
+'ds 00 \"';
+'ig 00 ';
# $Header$
-$usage = "Usage: xsubpp [-ansi] [-C++] [-except] [-tm typemap] file.xs\n";
+$usage = "Usage: xsubpp [-C++] [-except] [-typemap typemap] file.xs\n";
SWITCH: while ($ARGV[0] =~ s/^-//) {
$flag = shift @ARGV;
- $ansiflag = 1, next SWITCH if $flag eq 'ansi';
$spat = shift, next SWITCH if $flag eq 's';
$cplusplus = 1, next SWITCH if $flag eq 'C++';
$except = 1, next SWITCH if $flag eq 'except';
@@ -15,6 +17,7 @@ SWITCH: while ($ARGV[0] =~ s/^-//) {
@ARGV == 1 or die $usage;
chop($pwd = `pwd`);
($dir, $filename) = @ARGV[0] =~ m#(.*)/(.*)#
+ or ($dir, $filename) = @ARGV[0] =~ m#(.*[>\]])(.*)#
or ($dir, $filename) = ('.', $ARGV[0]);
chdir($dir);
@@ -43,7 +46,7 @@ foreach $typemap (@tm) {
}
else {
s/\s*$//;
-# $input_expr{$_} = '';
+ $input_expr{$_} = '';
$current = \$input_expr{$_};
}
}
@@ -53,7 +56,7 @@ foreach $typemap (@tm) {
}
else {
s/\s*$//;
-# $output_expr{$_} = '';
+ $output_expr{$_} = '';
$current = \$output_expr{$_};
}
}
@@ -76,9 +79,9 @@ sub Q {
open(F, $filename) || die "cannot open $filename\n";
while (<F>) {
- last if ($Module, $foo, $Package, $foo1, $Prefix) =
- /^MODULE\s*=\s*(\w+)(\s+PACKAGE\s*=\s*([\w:]+))?(\s+PREFIX\s*=\s*(\S+))?$/;
- print $_;
+ last if ($Module, $foo, $Package, $foo1, $Prefix) =
+ /^MODULE\s*=\s*([\w:]+)(\s+PACKAGE\s*=\s*([\w:]+))?(\s+PREFIX\s*=\s*(\S+))?\s*$/;
+ print $_;
}
exit 0 if $_ eq "";
$lastline = $_;
@@ -88,17 +91,20 @@ sub fetch_para {
@line = ();
if ($lastline ne "") {
if ($lastline =~
- /^MODULE\s*=\s*(\w+)(\s+PACKAGE\s*=\s*([\w:]+))?(\s+PREFIX\s*=\s*(\S+))?$/) {
+ /^MODULE\s*=\s*([\w:]+)(\s+PACKAGE\s*=\s*([\w:]+))?(\s+PREFIX\s*=\s*(\S+))?\s*$/) {
$Module = $1;
$foo = $2;
$Package = $3;
$foo1 = $4;
$Prefix = $5;
+ ($Module_cname = $Module) =~ s/\W/_/g;
($Packid = $Package) =~ s/:/_/g;
$Packprefix = $Package;
$Packprefix .= "::" if defined $Packprefix && $Packprefix ne "";
while (<F>) {
chop;
+ next if /^#/ &&
+ !/^#[ \t]*(if|ifdef|ifndef|else|elif|endif|define|undef)\b/;
last if /^\S/;
}
push(@line, $_) if $_ ne "";
@@ -108,7 +114,8 @@ sub fetch_para {
}
$lastline = "";
while (<F>) {
- next if /^#/ && !/^#(if|ifdef|else|elif|endif|define|undef)\b/;
+ next if /^#/ &&
+ !/^#[ \t]*(if|ifdef|ifndef|else|elif|endif|define|undef)\b/;
chop;
if (/^\S/ && @line && $line[-1] eq "") {
$lastline = $_;
@@ -118,8 +125,9 @@ sub fetch_para {
push(@line, $_);
}
}
- pop(@line) while @line && $line[-1] eq "";
+ pop(@line) while @line && $line[-1] =~ /^\s*$/;
}
+ $PPCODE = grep(/PPCODE:/, @line);
scalar @line;
}
@@ -135,6 +143,10 @@ while (&fetch_para) {
# extract return type, function name and arguments
$ret_type = shift(@line);
+ if ($ret_type =~ /^BOOT:/) {
+ push (@BootCode, @line, "", "") ;
+ next ;
+ }
if ($ret_type =~ /^static\s+(.*)$/) {
$static = 1;
$ret_type = $1;
@@ -149,10 +161,17 @@ while (&fetch_para) {
push(@Func_name, "${Packid}_$func_name");
push(@Func_pname, $pname);
@args = split(/\s*,\s*/, $orig_args);
- if (defined($class) && !defined($static)) {
+ if (defined($class)) {
+ if (defined($static)) {
+ unshift(@args, "CLASS");
+ $orig_args = "CLASS, $orig_args";
+ $orig_args =~ s/^CLASS, $/CLASS/;
+ }
+ else {
unshift(@args, "THIS");
$orig_args = "THIS, $orig_args";
$orig_args =~ s/^THIS, $/THIS/;
+ }
}
$orig_args =~ s/"/\\"/g;
$min_args = $num_args = @args;
@@ -172,7 +191,7 @@ while (&fetch_para) {
$defaults{$args[$i]} =~ s/"/\\"/g;
}
}
- if (defined($class) && !defined($static)) {
+ if (defined($class)) {
$func_args = join(", ", @args[1..$#args]);
} else {
$func_args = join(", ", @args);
@@ -180,23 +199,11 @@ while (&fetch_para) {
@args_match{@args} = 1..@args;
# print function header
- if ($ansiflag) {
- print Q<<"EOF";
-#static int
-#XS_${Packid}_$func_name(int, int ax, int items)
-#[[
-EOF
- }
- else {
- print Q<<"EOF";
-#static int
-#XS_${Packid}_$func_name(ix, ax, items)
-#register int ix;
-#register int ax;
-#register int items;
+ print Q<<"EOF";
+#XS(XS_${Packid}_$func_name)
#[[
+# dXSARGS;
EOF
- }
if ($elipsis) {
$cond = qq(items < $min_args);
}
@@ -218,6 +225,10 @@ EOF
# }
EOF
+ print Q<<"EOF" if $PPCODE;
+# SP -= items;
+EOF
+
# Now do a block of some sort.
$condnum = 0;
@@ -258,6 +269,9 @@ EOF
$_ = shift(@line);
last if /^\s*NOT_IMPLEMENTED_YET/;
last if /^\s*(PPCODE|CODE|OUTPUT|CLEANUP|CASE)\s*:/;
+ # Catch common error. Much more error checking required here.
+ blurt("Error: no tab in $pname argument declaration '$_'\n")
+ unless (m/\S+\s*\t\s*\S+/);
($var_type, $var_name, $var_init) =
/\s*([^\t]+)\s*([^\s=]+)\s*(=.*)?/;
if ($var_name =~ /^&/) {
@@ -286,10 +300,17 @@ EOF
print "\t$var_name;\n";
}
}
- if (!$thisdone && defined($class) && !defined($static)) {
+ if (!$thisdone && defined($class)) {
+ if (defined($static)) {
+ print "\tchar *";
+ $var_types{"CLASS"} = "char *";
+ &generate_init("char *", 1, "CLASS");
+ }
+ else {
print "\t$class *";
$var_types{"THIS"} = "$class *";
&generate_init("$class *", 1, "THIS");
+ }
}
# do code
@@ -303,14 +324,14 @@ EOF
$var_types{"RETVAL"} = $ret_type;
}
if (/^\s*PPCODE:/) {
- print "\tdSP;\n";
print $deferred;
while (@line) {
$_ = shift(@line);
- last if /^\s*(OUTPUT|CLEANUP|CASE)\s*:/;
+ die "PPCODE must be last thing"
+ if /^\s*(OUTPUT|CLEANUP|CASE)\s*:/;
print "$_\n";
}
- print "\tax = sp - stack_base;\n";
+ print "\tPUTBACK;\n\treturn;\n";
} elsif (/^\s*CODE:/) {
print $deferred;
while (@line) {
@@ -318,6 +339,10 @@ EOF
last if /^\s*(OUTPUT|CLEANUP|CASE)\s*:/;
print "$_\n";
}
+ } elsif ($func_name eq "DESTROY") {
+ print $deferred;
+ print "\n\t";
+ print "delete THIS;\n"
} else {
print $deferred;
print "\n\t";
@@ -325,7 +350,12 @@ EOF
print "RETVAL = ";
}
if (defined($static)) {
+ if ($func_name =~ /^new/) {
+ $func_name = "$class";
+ }
+ else {
print "$class::";
+ }
} elsif (defined($class)) {
print "THIS->";
}
@@ -346,7 +376,7 @@ EOF
s/^\s+//;
($outarg, $outcode) = split(/\t+/);
if ($outcode) {
- print "\t$outcode\n";
+ print "\t$outcode\n";
} else {
die "$outarg not an argument"
unless defined($args_match{$outarg});
@@ -383,12 +413,17 @@ EOF
unshift(@line, $_);
}
}
+
print Q<<EOF if $except;
# if (errbuf[0])
# croak(errbuf);
EOF
+
+ print Q<<EOF unless $PPCODE;
+# XSRETURN(1);
+EOF
+
print Q<<EOF;
-# return ax;
#]]
#
EOF
@@ -397,24 +432,32 @@ EOF
# print initialization routine
print qq/extern "C"\n/ if $cplusplus;
print Q<<"EOF";
-#int boot_$Module(ix,ax,items)
-#int ix;
-#int ax;
-#int items;
+#XS(boot_$Module_cname)
#[[
+# dXSARGS;
# char* file = __FILE__;
#
EOF
for (@Func_name) {
$pname = shift(@Func_pname);
- print " newXSUB(\"$pname\", 0, XS_$_, file);\n";
+ print " newXS(\"$pname\", XS_$_, file);\n";
+}
+
+if (@BootCode)
+{
+ print "\n /* Initialisation Section */\n\n" ;
+ print grep (s/$/\n/, @BootCode) ;
+ print " /* End of Initialisation Section */\n\n" ;
}
+
+print " ST(0) = &sv_yes;\n";
+print " XSRETURN(1);\n";
print "}\n";
sub output_init {
local($type, $num, $init) = @_;
- local($arg) = "ST($num)";
+ local($arg) = "ST(" . ($num - 1) . ")";
eval qq/print " $init\\\n"/;
}
@@ -423,7 +466,7 @@ sub blurt { warn @_; $errors++ }
sub generate_init {
local($type, $num, $var) = @_;
- local($arg) = "ST($num)";
+ local($arg) = "ST(" . ($num - 1) . ")";
local($argoff) = $num - 1;
local($ntype);
local($tk);
@@ -443,7 +486,7 @@ sub generate_init {
$subexpr =~ s/\$arg/ST(ix_$var)/g;
$subexpr =~ s/\n\t/\n\t\t/g;
$subexpr =~ s/is not of (.*")/[arg %d] is not of $1, ix_$var + 1/g;
- $subexpr =~ s/\$var/$var[ix_$var - $argoff]/;
+ $subexpr =~ s/\$var/${var}[ix_$var - $argoff]/;
$expr =~ s/DO_ARRAY_ELEM/$subexpr/;
}
if (defined($defaults{$var})) {
@@ -461,7 +504,7 @@ sub generate_init {
sub generate_output {
local($type, $num, $var) = @_;
- local($arg) = "ST($num)";
+ local($arg) = "ST(" . ($num - ($num != 0)) . ")";
local($argoff) = $num - 1;
local($ntype);
@@ -483,18 +526,27 @@ sub generate_output {
$subexpr =~ s/\$var/${var}[ix_$var]/g;
$subexpr =~ s/\n\t/\n\t\t/g;
$expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
- eval "print qq\f$expr\f";
+ eval "print qq\a$expr\a";
}
- elsif ($arg eq 'ST(0)') {
+ elsif ($var eq 'RETVAL') {
if ($expr =~ /^\t\$arg = /) {
- eval "print qq\f$expr\f";
+ eval "print qq\a$expr\a";
print "\tsv_2mortal(ST(0));\n";
}
else {
print "\tST(0) = sv_newmortal();\n";
- eval "print qq\f$expr\f";
+ eval "print qq\a$expr\a";
}
}
+ elsif ($arg =~ /^ST\(\d+\)$/) {
+ eval "print qq\a$expr\a";
+ }
+ elsif ($arg =~ /^ST\(\d+\)$/) {
+ eval "print qq\a$expr\a";
+ }
+ elsif ($arg =~ /^ST\(\d+\)$/) {
+ eval "print qq\a$expr\a";
+ }
}
}
@@ -510,3 +562,55 @@ sub map_type {
}
exit $errors;
+
+##############################################################################
+
+ # These next few lines are legal in both Perl and nroff.
+
+.00 ; # finish .ig
+
+'di \" finish diversion--previous line must be blank
+.nr nl 0-1 \" fake up transition to first page again
+.nr % 0 \" start at page 1
+'; __END__ ############# From here on it's a standard manual page ############
+.TH XSUBPP 1 "August 9, 1994"
+.AT 3
+.SH NAME
+xsubpp \- compiler to convert Perl XS code into C code
+.SH SYNOPSIS
+.B xsubpp [-C++] [-except] [-typemap typemap] file.xs
+.SH DESCRIPTION
+.I xsubpp
+will compile XS code into C code by embedding the constructs necessary to
+let C functions manipulate Perl values and creates the glue necessary to let
+Perl access those functions. The compiler uses typemaps to determine how
+to map C function parameters and variables to Perl values.
+.PP
+The compiler will search for typemap files called
+.I typemap.
+It will use the following search path to find default typemaps, with the
+rightmost typemap taking precedence.
+.br
+.nf
+ ../../../typemap:../../typemap:../typemap:typemap
+.fi
+.SH OPTIONS
+.TP
+.B \-C++
+.br
+Adds ``extern "C"'' to the C code.
+.TP
+.B \-except
+Adds exception handling stubs to the C code.
+.TP
+.B \-typemap typemap
+Indicates that a user-supplied typemap should take precedence over the
+default typemaps. This option may be used multiple times, with the last
+typemap having the highest precedence.
+.SH ENVIRONMENT
+No environment variables are used.
+.SH AUTHOR
+Larry Wall
+.SH "SEE ALSO"
+perl(1)
+.ex