shell bypass 403
package ExtUtils::XSBuilder::C::grammar;
# initial grammar is taken from Inline::C::grammar & Inline::Struct::grammar
use strict;
use vars qw{$VERSION @EXPORT @ISA} ;
use Exporter ;
use Data::Dumper ;
$VERSION = '0.30';
@ISA = qw{Exporter} ;
@EXPORT = qw{cdef_define cdef_enum cdef_struct cdef_function_declaration} ;
# ============================================================================
sub cdef_define
{
my ($thisparser, $name, $comment) = @_ ;
my $elem = { name => $name, $comment?(comment => $comment):() } ;
if ($thisparser->{srcobj}->handle_define($elem))
{
push @{$thisparser->{data}{constants}}, $elem ;
print "constant: $name\n" ;
}
else
{
print "constant: $name (ignore because handle_define returned false)\n" ;
}
}
# ============================================================================
sub cdef_enum
{
my ($thisparser, $names) = @_ ;
for (@{$names})
{
if (ref $_)
{
my $elem = { name => $_ -> [0], $_->[1] && @{$_->[1]}?('comment' => join (' ', @{$_->[1]})):() } ;
push @{$thisparser->{data}{constants}}, $elem if ($thisparser->{srcobj}->handle_enum($elem)) ;
}
}
1 ;
}
# ============================================================================
sub cdef_struct
{
my ($thisparser, $perlname, $cname, $fields, $type) = @_;
my $seen = \$thisparser->{data}{structure}{$cname || $type} ;
my $s = $$seen ;
return 0 if ($s && ($s -> {elts} && !$type)) ;
#print "cdef $cname $type\n" ;
$s ||= {} ;
$s -> {type} ||= $cname ;
$s -> {type} = $type if ($type) ;
if ($fields)
{
my @fields;
my @comment ;
for (@$fields)
{
if (ref $_)
{
push @fields, {
'type' => $_->[0],
'name' => $_->[1],
($_->[2] && @{$_->[2]}) || @comment?('comment' => join (' ', @{$_->[2]}, @comment)):(),
$_->[3] && @{$_->[3]}?('args' => $_->[3]):(),
} ;
@comment = () ;
}
else
{
push @comment, $_ ;
}
}
$s -> {elts} = \@fields ;
}
$s -> {stype} = $cname if ($cname) ;
if ($fields)
{
if ($thisparser->{srcobj}->handle_struct($s))
{
push @{$thisparser->{data}{structures}}, $s ;
print "struct: $cname (type=$type)\n" ;
}
else
{
print "struct: $cname (ignore because handle_struct returned false)\n" ;
}
}
$$seen = $s ;
return $s ;
}
# ============================================================================
sub cdef_function_declaration
{
my ($thisparser, $function, $rettype, $args) = @_ ;
return 0 if (!$function) ;
return 0 if ($thisparser->{data}{function}{$function}++) ;
my $s = { 'name' => $function } ;
my $dummy = 'arg0' ;
$s -> {return_type} = $rettype ;
my @args ;
my $i = 0 ;
for (@{$args})
{
if (ref $_)
{
push @args, {
'type' => $_->[0],
'name' => $_->[1] || "arg$i",
} if ($_->[0] ne 'void') ;
}
$i++ ;
}
$s -> {args} = \@args ;
if ($thisparser->{srcobj}->handle_function($s))
{
push @{$thisparser->{data}{functions}}, $s ;
print "func: $function\n" ;
}
else
{
print "func: $function (ignore because handle_function returned false)\n" ;
}
return $s ;
}
# ============================================================================
sub grammar {
<<'END';
{
use ExtUtils::XSBuilder::C::grammar ; # import cdef_xxx functions
}
code: comment_part(s) {1}
comment_part:
comment(s?) part
{
#print "comment: ", Data::Dumper::Dumper(\@item) ;
$item[2] -> {comment} = "@{$item[1]}" if (ref $item[1] && @{$item[1]} && ref $item[2]) ;
1 ;
}
| comment
part:
prepart
| stdpart
{
if ($thisparser -> {my_neednewline})
{
print "\n" ;
$thisparser -> {my_neednewline} = 0 ;
}
$return = $item[1] ;
}
# prepart can be used to extent the parser (for default it always fails)
prepart: '?'
{0}
stdpart:
define
{
$return = cdef_define ($thisparser, $item[1][0], $item[1][1]) ;
}
| struct
{
$return = cdef_struct ($thisparser, @{$item[1]}) ;
}
| enum
{
$return = cdef_enum ($thisparser, $item[1][1]) ;
}
| function_declaration
{
$return = cdef_function_declaration ($thisparser, @{$item[1]}) ;
}
| struct_typedef
{
my ($type,$alias) = @{$item[1]}[0,1];
$return = cdef_struct ($thisparser, undef, $type, undef, $alias) ;
}
| comment
| anything_else
comment:
m{\s* // \s* ([^\n]*) \s*? \n }x
{ $1 }
| m{\s* /\* \s* ([^*]+|\*(?!/))* \s*? \*/ ([ \t]*)? }x
{ $item[1] =~ m#/\*\s*?(.*?)\s*?\*/#s ; $1 }
semi_linecomment:
m{;\s*\n}x
{
$return = [] ;
1 ;
}
| ';' comment(s?)
{
$item[2]
}
function_definition:
rtype IDENTIFIER '(' <leftop: arg ',' arg>(s?) ')' '{'
{[@item[2,1], $item[4]]}
pTHX:
'pTHX_'
function_declaration:
type_identifier '(' pTHX(?) <leftop: arg_decl ',' arg_decl>(s?) ')' function_declaration_attr ( ';' | '{' )
{
#print Data::Dumper::Dumper (\@item) ;
[
$item[1][1],
$item[1][0],
@{$item[3]}?[['pTHX', 'aTHX' ], @{$item[4]}]:$item[4]
]
}
define:
'#define' IDENTIFIER /.*?\n/
{
$item[3] =~ m{(?:/\*\s*(.*?)\s*\*/|//\s*(.*?)\s*$)} ; [$item[2], $1]
}
ignore_cpp:
'#' /.*?\n/
struct:
'struct' IDENTIFIER '{' field(s) '}' ';'
{
# [perlname, cname, fields]
[$item[2], "@item[1,2]", $item[4]]
}
| 'typedef' 'struct' '{' field(s) '}' IDENTIFIER ';'
{
# [perlname, cname, fields]
[$item[6], undef, $item[4], $item[6]]
}
| 'typedef' 'struct' IDENTIFIER '{' field(s) '}' IDENTIFIER ';'
{
# [perlname, cname, fields, alias]
[$item[3], "@item[2,3]", $item[5], $item[7]]
}
struct_typedef:
'typedef' 'struct' IDENTIFIER IDENTIFIER ';'
{
["@item[2,3]", $item[4]]
}
enum:
'enum' IDENTIFIER '{' enumfield(s) '}' ';'
{
[$item[2], $item[4]]
}
| 'typedef' 'enum' '{' enumfield(s) '}' IDENTIFIER ';'
{
[undef, $item[4], $item[6]]
}
| 'typedef' 'enum' IDENTIFIER '{' enumfield(s) '}' IDENTIFIER ';'
{
[$item[3], $item[5], $item[7]]
}
field:
comment
| define
{
$return = cdef_define ($thisparser, $item[1][0], $item[1][1]) ;
}
| valuefield
| callbackfield
| ignore_cpp
valuefield:
type_identifier comment(s?) semi_linecomment
{
$thisparser -> {my_neednewline} = 1 ;
print " valuefield: $item[1][0] : $item[1][1]\n" ;
[$item[1][0], $item[1][1], [$item[2]?@{$item[2]}:() , $item[3]?@{$item[3]}:()] ]
}
callbackfield:
rtype '(' '*' IDENTIFIER ')' '(' <leftop: arg_decl ',' arg_decl>(s?) ')' comment(s?) semi_linecomment
{
my $type = "$item[1](*)(" . join(',', map { "$_->[0] $_->[1]" } @{$item[7]}) . ')' ;
my $dummy = 'arg0' ;
my @args ;
for (@{$item[7]})
{
if (ref $_)
{
push @args, {
'type' => $_->[0],
'name' => $_->[1],
} if ($_->[0] ne 'void') ;
}
}
my $s = { 'name' => $type, 'return_type' => $item[1], args => \@args } ;
push @{$thisparser->{data}{callbacks}}, $s if ($thisparser->{srcobj}->handle_callback($s)) ;
$thisparser -> {my_neednewline} = 1 ;
print " callbackfield: $type : $item[4]\n" ;
[$type, $item[4], [$item[9]?@{$item[9]}:() , $item[10]?@{$item[10]}:()]] ;
}
enumfield:
comment
| IDENTIFIER comment(s?) /,?/ comment(s?)
{
[$item[1], [$item[2]?@{$item[2]}:() , $item[4]?@{$item[4]}:()] ] ;
}
rtype:
modmodifier(s) TYPE star(s?)
{
my @modifier = @{$item[1]} ;
shift @modifier if ($modifier[0] eq 'extern' || $modifier[0] eq 'static') ;
$return = join ' ',@modifier, $item[2] ;
$return .= join '',' ',@{$item[3]} if @{$item[3]};
1 ;
}
| TYPE(s) star(s?)
{
$return = join (' ', @{$item[1]}) ;
$return .= join '',' ',@{$item[2]} if @{$item[2]};
#print "rtype $return \n" ;
1 ;
}
modifier(s) star(s?)
{
join ' ',@{$item[1]}, @{$item[2]} ;
}
arg:
type_identifier
{[$item[1][0],$item[1][1]]}
| '...'
{['...']}
arg_decl:
rtype '(' '*' IDENTIFIER ')' '(' <leftop: arg_decl ',' arg_decl>(s?) ')'
{
my $type = "$item[1](*)(" . join(',', map { "$_->[0] $_->[1]" } @{$item[7]}) . ')' ;
my $dummy = 'arg0' ;
my @args ;
for (@{$item[7]})
{
if (ref $_)
{
push @args, {
'type' => $_->[0],
'name' => $_->[1],
} if ($_->[0] ne 'void') ;
}
}
my $s = { 'name' => $type, 'return_type' => $item[1], args => \@args } ;
push @{$thisparser->{data}{callbacks}}, $s if ($thisparser->{srcobj}->handle_callback($s)) ;
[$type, $item[4], [$item[9]?@{$item[9]}:() , $item[11]?@{$item[11]}:()]] ;
}
| 'pTHX'
{
['pTHX', 'aTHX' ]
}
| type_identifier
{
[$item[1][0], $item[1][1] ]
}
| '...'
{['...']}
function_declaration_attr:
type_identifier:
type_varname
{
my $r ;
my @type = @{$item[1]} ;
#print "type = @type\n" ;
my $name = pop @type ;
if (@type && ($name !~ /\*/))
{
$r = [join (' ', @type), $name]
}
else
{
$r = [join (' ', @{$item[1]})] ;
}
#print "r = @$r\n" ;
$r ;
}
type_varname:
attribute(s?) TYPE(s) star(s) varname(?)
{
[@{$item[1]}, @{$item[2]}, @{$item[3]}, @{$item[4]}] ;
}
| attribute(s?) varname(s)
{
$item[2] ;
}
varname:
##IDENTIFIER '[' IDENTIFIER ']'
IDENTIFIER '[' /[^]]+/ ']'
{
"$item[1]\[$item[3]\]" ;
}
| IDENTIFIER ':' IDENTIFIER
{
$item[1]
}
| IDENTIFIER
{
$item[1]
}
star: '*' | 'const' '*'
modifier: 'const' | 'struct' | 'enum' | 'unsigned' | 'long' | 'extern' | 'static' | 'short' | 'signed'
modmodifier: 'const' | 'struct' | 'enum' | 'extern' | 'static'
attribute: 'extern' | 'static'
# IDENTIFIER: /[a-z]\w*/i
IDENTIFIER: /\w+/
TYPE: /\w+/
anything_else: /.*/
END
}
1;
__END__
=pod
| function_definition
{
my $function = $item[1][0];
$return = 1, last if $thisparser->{data}{done}{$function}++;
push @{$thisparser->{data}{functions}}, $function;
$thisparser->{data}{function}{$function}{return_type} =
$item[1][1];
$thisparser->{data}{function}{$function}{arg_types} =
[map {ref $_ ? $_->[0] : '...'} @{$item[1][2]}];
$thisparser->{data}{function}{$function}{arg_names} =
[map {ref $_ ? $_->[1] : '...'} @{$item[1][2]}];
}
=cut