⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xsubpp

📁 UNIX下perl实现代码
💻
📖 第 1 页 / 共 4 页
字号:
    print $_;}&Exit unless defined $_;print "$xsubpp::counter::SECTION_END_MARKER\n" if $WantLineNumbers;$lastline    = $_;$lastline_no = $.;# Read next xsub into @line from ($lastline, <$FH>).sub fetch_para {    # parse paragraph    death ("Error: Unterminated `#if/#ifdef/#ifndef'")	if !defined $lastline && $XSStack[-1]{type} eq 'if';    @line = ();    @line_no = () ;    return PopFile() if !defined $lastline;    if ($lastline =~	/^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/) {	$Module = $1;	$Package = defined($2) ? $2 : '';	# keep -w happy	$Prefix  = defined($3) ? $3 : '';	# keep -w happy	$Prefix = quotemeta $Prefix ;	($Module_cname = $Module) =~ s/\W/_/g;	($Packid = $Package) =~ tr/:/_/;	$Packprefix = $Package;	$Packprefix .= "::" if $Packprefix ne "";	$lastline = "";    }    for(;;) {	# Skip embedded PODs 	while ($lastline =~ /^=/) {    	    while ($lastline = <$FH>) {	    	last if ($lastline =~ /^=cut\s*$/);	    }	    death ("Error: Unterminated pod") unless $lastline;	    $lastline = <$FH>;	    chomp $lastline;	    $lastline =~ s/^\s+$//;	}	if ($lastline !~ /^\s*#/ ||	    # CPP directives:	    #	ANSI:	if ifdef ifndef elif else endif define undef	    #		line error pragma	    #	gcc:	warning include_next	    #   obj-c:	import	    #   others:	ident (gcc notes that some cpps have this one)	    $lastline =~ /^#[ \t]*(?:(?:if|ifn?def|elif|else|endif|define|undef|pragma|error|warning|line\s+\d+|ident)\b|(?:include(?:_next)?|import)\s*["<].*[>"])/) {	    last if $lastline =~ /^\S/ && @line && $line[-1] eq "";	    push(@line, $lastline);	    push(@line_no, $lastline_no) ;	}	# Read next line and continuation lines	last unless defined($lastline = <$FH>);	$lastline_no = $.;	my $tmp_line;	$lastline .= $tmp_line	    while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>));	chomp $lastline;	$lastline =~ s/^\s+$//;    }    pop(@line), pop(@line_no) while @line && $line[-1] eq "";    1;}PARAGRAPH:while (fetch_para()) {    # Print initial preprocessor statements and blank lines    while (@line && $line[0] !~ /^[^\#]/) {	my $line = shift(@line);	print $line, "\n";	next unless $line =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;	my $statement = $+;	if ($statement eq 'if') {	    $XSS_work_idx = @XSStack;	    push(@XSStack, {type => 'if'});	} else {	    death ("Error: `$statement' with no matching `if'")		if $XSStack[-1]{type} ne 'if';	    if ($XSStack[-1]{varname}) {		push(@InitFileCode, "#endif\n");		push(@BootCode,     "#endif");	    }	    my(@fns) = keys %{$XSStack[-1]{functions}};	    if ($statement ne 'endif') {		# Hide the functions defined in other #if branches, and reset.		@{$XSStack[-1]{other_functions}}{@fns} = (1) x @fns;		@{$XSStack[-1]}{qw(varname functions)} = ('', {});	    } else {		my($tmp) = pop(@XSStack);		0 while (--$XSS_work_idx			 && $XSStack[$XSS_work_idx]{type} ne 'if');		# Keep all new defined functions		push(@fns, keys %{$tmp->{other_functions}});		@{$XSStack[$XSS_work_idx]{functions}}{@fns} = (1) x @fns;	    }	}    }    next PARAGRAPH unless @line;    if ($XSS_work_idx && !$XSStack[$XSS_work_idx]{varname}) {	# We are inside an #if, but have not yet #defined its xsubpp variable.	print "#define $cpp_next_tmp 1\n\n";	push(@InitFileCode, "#if $cpp_next_tmp\n");	push(@BootCode,     "#if $cpp_next_tmp");	$XSStack[$XSS_work_idx]{varname} = $cpp_next_tmp++;    }    death ("Code is not inside a function"	   ." (maybe last function was ended by a blank line "	   ." followed by a a statement on column one?)")	if $line[0] =~ /^\s/;    # initialize info arrays    undef(%args_match);    undef(%var_types);    undef(%defaults);    undef($class);    undef($static);    undef($elipsis);    undef($wantRETVAL) ;    undef($RETVAL_no_return) ;    undef(%arg_list) ;    undef(@proto_arg) ;    undef(@arg_with_types) ;    undef($processing_arg_with_types) ;    undef(%arg_types) ;    undef(@outlist) ;    undef(%in_out) ;    undef($proto_in_this_xsub) ;    undef($scope_in_this_xsub) ;    undef($interface);    undef($prepush_done);    $interface_macro = 'XSINTERFACE_FUNC' ;    $interface_macro_set = 'XSINTERFACE_FUNC_SET' ;    $ProtoThisXSUB = $WantPrototypes ;    $ScopeThisXSUB = 0;    $xsreturn = 0;    $_ = shift(@line);    while ($kwd = check_keyword("REQUIRE|PROTOTYPES|VERSIONCHECK|INCLUDE")) {        &{"${kwd}_handler"}() ;        next PARAGRAPH unless @line ;        $_ = shift(@line);    }    if (check_keyword("BOOT")) {	&check_cpp;	push (@BootCode, "#line $line_no[@line_no - @line] \"$filename\"")	  if $WantLineNumbers && $line[0] !~ /^\s*#\s*line\b/;        push (@BootCode, @line, "") ;        next PARAGRAPH ;    }    # extract return type, function name and arguments    ($ret_type) = TidyType($_);    $RETVAL_no_return = 1 if $ret_type =~ s/^NO_OUTPUT\s+//;    # Allow one-line ANSI-like declaration    unshift @line, $2      if $process_argtypes	and $ret_type =~ s/^(.*?\w.*?)\s*\b(\w+\s*\(.*)/$1/s;    # a function definition needs at least 2 lines    blurt ("Error: Function definition too short '$ret_type'"), next PARAGRAPH	unless @line ;    $static = 1 if $ret_type =~ s/^static\s+//;    $func_header = shift(@line);    blurt ("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH	unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s;    ($class, $func_name, $orig_args) =  ($1, $2, $3) ;    $class = "$4 $class" if $4;    ($pname = $func_name) =~ s/^($Prefix)?/$Packprefix/;    ($clean_func_name = $func_name) =~ s/^$Prefix//;    $Full_func_name = "${Packid}_$clean_func_name";    if ($Is_VMS) { $Full_func_name = $SymSet->addsym($Full_func_name); }    # Check for duplicate function definition    for $tmp (@XSStack) {	next unless defined $tmp->{functions}{$Full_func_name};	Warn("Warning: duplicate function definition '$clean_func_name' detected");	last;    }    $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;    %XsubAliases = %XsubAliasValues = %Interfaces = @Attributes = ();    $DoSetMagic = 1;    $orig_args =~ s/\\\s*/ /g;		# process line continuations    my %only_outlist;    if ($process_argtypes and $orig_args =~ /\S/) {	my $args = "$orig_args ,";	if ($args =~ /^( (??{ $C_arg }) , )* $ /x) {	    @args = ($args =~ /\G ( (??{ $C_arg }) ) , /xg);	    for ( @args ) {		s/^\s+//;		s/\s+$//;		my $arg = $_;		my $default;		($arg, $default) = / ( [^=]* ) ( (?: = .* )? ) /x;		my ($pre, $name) = ($arg =~ /(.*?) \s* \b(\w+) \s* $ /x);		next unless length $pre;		my $out_type;		my $inout_var;		if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//) {		    my $type = $1;		    $out_type = $type if $type ne 'IN';		    $arg =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//;		}		if (/\W/) {	# Has a type		    push @arg_with_types, $arg;		    # warn "pushing '$arg'\n";		    $arg_types{$name} = $arg;		    $_ = "$name$default";		}		$only_outlist{$_} = 1 if $out_type eq "OUTLIST";		push @outlist, $name if $out_type =~ /OUTLIST$/;		$in_out{$name} = $out_type if $out_type;	    }	} else {	    @args = split(/\s*,\s*/, $orig_args);	    Warn("Warning: cannot parse argument list '$orig_args', fallback to split");	}    } else {	@args = split(/\s*,\s*/, $orig_args);	for (@args) {	    if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|IN_OUT|OUT)\s+//) {		my $out_type = $1;		next if $out_type eq 'IN';		$only_outlist{$_} = 1 if $out_type eq "OUTLIST";		push @outlist, $name if $out_type =~ /OUTLIST$/;		$in_out{$_} = $out_type;	    }	}    }    if (defined($class)) {	my $arg0 = ((defined($static) or $func_name eq 'new')		    ? "CLASS" : "THIS");	unshift(@args, $arg0);	($report_args = "$arg0, $report_args") =~ s/^\w+, $/$arg0/;    }    my $extra_args = 0;    @args_num = ();    $num_args = 0;    my $report_args = '';    foreach $i (0 .. $#args) {	    if ($args[$i] =~ s/\.\.\.//) {		    $elipsis = 1;		    if ($args[$i] eq '' && $i == $#args) {		        $report_args .= ", ...";			pop(@args);			last;		    }	    }	    if ($only_outlist{$args[$i]}) {		push @args_num, undef;	    } else {		push @args_num, ++$num_args;		$report_args .= ", $args[$i]";	    }	    if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {		    $extra_args++;		    $args[$i] = $1;		    $defaults{$args[$i]} = $2;		    $defaults{$args[$i]} =~ s/"/\\"/g;	    }	    $proto_arg[$i+1] = "\$" ;    }    $min_args = $num_args - $extra_args;    $report_args =~ s/"/\\"/g;    $report_args =~ s/^,\s+//;    my @func_args = @args;    shift @func_args if defined($class);    for (@func_args) {	s/^/&/ if $in_out{$_};    }    $func_args = join(", ", @func_args);    @args_match{@args} = @args_num;    $PPCODE = grep(/^\s*PPCODE\s*:/, @line);    $CODE = grep(/^\s*CODE\s*:/, @line);    # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)    #   to set explicit return values.    $EXPLICIT_RETURN = ($CODE &&		("@line" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));    $ALIAS  = grep(/^\s*ALIAS\s*:/,  @line);    $INTERFACE  = grep(/^\s*INTERFACE\s*:/,  @line);    $xsreturn = 1 if $EXPLICIT_RETURN;    # print function header    print Q<<"EOF";#XS(XS_${Full_func_name})#[[#    dXSARGS;EOF    print Q<<"EOF" if $ALIAS ;#    dXSI32;EOF    print Q<<"EOF" if $INTERFACE ;#    dXSFUNCTION($ret_type);EOF    if ($elipsis) {	$cond = ($min_args ? qq(items < $min_args) : 0);    }    elsif ($min_args == $num_args) {	$cond = qq(items != $min_args);    }    else {	$cond = qq(items < $min_args || items > $num_args);    }    print Q<<"EOF" if $except;#    char errbuf[1024];#    *errbuf = '\0';EOF    if ($ALIAS)       { print Q<<"EOF" if $cond }#    if ($cond)#       Perl_croak(aTHX_ "Usage: %s($report_args)", GvNAME(CvGV(cv)));EOF    else       { print Q<<"EOF" if $cond }#    if ($cond)#	Perl_croak(aTHX_ "Usage: $pname($report_args)");EOF    print Q<<"EOF" if $PPCODE;#    SP -= items;EOF    # Now do a block of some sort.    $condnum = 0;    $cond = '';			# last CASE: condidional    push(@line, "$END:");    push(@line_no, $line_no[-1]);    $_ = '';    &check_cpp;    while (@line) {	&CASE_handler if check_keyword("CASE");	print Q<<"EOF";#   $except [[EOF	# do initialization of input variables	$thisdone = 0;	$retvaldone = 0;	$deferred = "";	%arg_list = () ;        $gotRETVAL = 0;	INPUT_handler() ;	process_keyword("INPUT|PREINIT|INTERFACE_MACRO|C_ARGS|ALIAS|ATTRS|PROTOTYPE|SCOPE") ;	print Q<<"EOF" if $ScopeThisXSUB;#   ENTER;#   [[EOF		if (!$thisdone && defined($class)) {	    if (defined($static) or $func_name eq 'new') {		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	if (/^\s*NOT_IMPLEMENTED_YET/) {		print "\n\tPerl_croak(aTHX_ \"$pname: not implemented yet\");\n";		$_ = '' ;	} else {		if ($ret_type ne "void") {			print "\t" . &map_type($ret_type, 'RETVAL') . ";\n"				if !$retvaldone;			$args_match{"RETVAL"} = 0;			$var_types{"RETVAL"} = $ret_type;			print "\tdXSTARG;\n"				if $WantOptimize and $targetable{$type_kind{$ret_type}};		}		if (@arg_with_types) {		    unshift @line, @arg_with_types, $_;		    $_ = "";		    $processing_arg_with_types = 1;		    INPUT_handler() ;		}		print $deferred;        process_keyword("INIT|ALIAS|ATTRS|PROTOTYPE|INTERFACE_MACRO|INTERFACE|C_ARGS") ;		if (check_keyword("PPCODE")) {			print_section();			death ("PPCODE must be last thing") if @line;			print "\tLEAVE;\n" if $ScopeThisXSUB;			print "\tPUTBACK;\n\treturn;\n";		} elsif (check_keyword("CODE")) {			print_section() ;		} elsif (defined($class) and $func_name eq "DESTROY") {			print "\n\t";			print "delete THIS;\n";		} else {			print "\n\t";			if ($ret_type ne "void") {				print "RETVAL = ";				$wantRETVAL = 1;			}			if (defined($static)) {			    if ($func_name eq 'new') {				$func_name = "$class";			    } else {				print "${class}::";			    }			} elsif (defined($class)) {			    if ($func_name eq 'new') {				$func_name .= " $class";			    } else {				print "THIS->";			    }			}			$func_name =~ s/^($spat)//			    if defined($spat);			$func_name = 'XSFUNCTION' if $interface;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -