1
# Represent any C type.
2
# Type contains the size of arrays, which is either constant
3
# or resolved (into an object) from resolveobj.
8
# new C::Type(resolveobj,str)
11
my $this = bless {},shift;
12
$this->{Resolve} = shift;
14
$this->parsefrom(shift);
21
if($str =~ /^\s*\w+\s*$/) {
23
$this->{ProtoName} = $str;
26
# Now, recall the different C syntaxes. First priority is a pointer:
28
if($str =~ /^\s*\*(.*)$/) {
29
$decl = $this->stripptrs($1);
31
} elsif($str =~ /^\s*\(.*\)\s*$/) {
32
# XXX Should try to see if a funccall.
33
return $this->stripptrs($1);
34
} elsif($str =~ /^(.*)\[([^]]+)\]\s*$/) {
36
print "ARR($str): ($siz)\n" if $::PP_VERBOSE;
37
$decl = $this->stripptrs($1);
38
unshift @$decl,"ARR($siz)";
39
print "ARR($str): ($siz)\n" if $::PP_VERBOSE;
41
die("Invalid C type '$str'");
47
# XXX Correct to *real* parsing. This is only a subset.
50
# First, take the words in the beginning
51
$str =~ /^\s*((?:\w+\b\s*)+)([^[].*)$/;
52
my $base = $1; my $decl = $2;
53
my $foo = $this->stripptrs($decl);
54
$this->{Base} = $base;
55
$this->{Chain} = $foo;
59
my($this,$name,$opts) = @_;
60
for(@{$this->{Chain}}) {
61
if($_ eq "PTR") {$name = "*$name"}
62
elsif($_ =~/^ARR\((.*)\)$/) {
63
if($opts->{VarArrays2Ptrs}) {
66
$name = "($name)[$1]";
69
else { confess("Invalid decl") }
71
return "$this->{Base} $name";
74
# Useful when parsing argument decls
75
sub protoname { return shift->{ProtoName} }
78
my($this,$from,$to) = @_;
80
if($#{$this->{Chain}} >= 0) {
81
# strdup loses portability :(
82
return "($to) = malloc(strlen($from)+1); strcpy($to,$from);"
83
if $this->{Base} =~ /^\s*char\s*$/;
84
return "($to) = newSVsv($from);"
85
if $this->{Base} =~ /^\s*SV\s*$/;
86
my $code = $this->get_malloc($to,$from);
87
my ($deref0,$deref1) = ($from,$to);
88
for(@{$this->{Chain}}) {
89
if($_ eq "PTR") {confess("Cannot alloc pointer, must be array");}
90
elsif($_ =~/^ARR\((.*)\)$/) {
93
if(!$deref0) {$deref1=0;}
94
else {int __malloc_ind_$no;
95
for(__malloc_ind_$no = 0;
96
__malloc_ind_$no < $1;
97
__malloc_ind_$no ++) {";
98
$deref0 = $deref0."[__malloc_ind_$no]";
99
$deref1 = $deref1."[__malloc_ind_$no]";
101
} else { confess("Invalid decl $_") }
103
$code .= "$prev $deref1 = $deref0; $close";
106
return "($to) = ($from);";
110
my($this,$from) = @_;
112
if($#{$this->{Chain}} >= 0) {
113
return "free($from);"
114
if $this->{Base} =~ /^\s*char\s*$/;
115
return "SvREFCNT_dec($from);"
116
if $this->{Base} =~ /^\s*SV\s*$/;
123
for(@{$this->{Chain}}) {
125
if($no > 1) {croak("Can only free one layer!\n");}
126
# if($_ eq "PTR") {confess("Cannot free pointer, must be array ;) (FIX CType.pm)");}
127
return "free($from);\n ";
136
return scalar grep /(ARR|PTR)/,(@{$this->{Chain}})
139
# Just returns with the array string.
141
my($this,$assignto) = @_;
143
my $deref = "$assignto";
147
for(@{$this->{Chain}}) {
148
if($_ eq "PTR") {confess("Cannot alloc pointer, must be array");}
149
elsif($_ =~/^ARR\((.*)\)$/) {
150
$str .= "$prev $assignto =
151
malloc(sizeof(* $assignto) * $1);
154
$prev = "{int __malloc_ind_$no;
155
for(__malloc_ind_$no = 0;
156
__malloc_ind_$no < $1;
157
__malloc_ind_$no ++) {";
158
$deref = $deref."[__malloc_ind_$no]";
160
} else { confess("Invalid decl $_") }
169
# Determine if everything constant and can just declare