1 # This file is part of The New Aspell
2 # Copyright (C) 2001-2002 by Kevin Atkinson under the GNU LGPL
3 # license version 2.0 or 2.1. You should have received a copy of the
4 # LGPL license along with this library if you did not you can find it
5 # at http://www.gnu.org/.
7 package MkSrc::CcHelper;
11 our @ISA = qw(Exporter);
12 our @EXPORT = qw(to_c_return_type c_error_cond
13 to_type_name make_desc make_func call_func
14 make_c_method call_c_method form_c_method
20 no warnings qw(uninitialized);
26 sub to_type_name ( $ $ ; \% );
28 =head1 Code Generation Modes
30 The code generation modes are currently one of the following:
32 cc: Mode used to create types suitable for C interface
33 cc_cxx: Like cc but typenames don't have a leading Aspell prefix
34 cxx: Mode used to create types suitable for CXX interface
35 native: Mode in which types are suitable for the internal implementation
36 native_no_err: Like Native but with out PosibErr return types
38 =head1 MkSrc::CcHelper
40 Helper functions used by interface generation code:
44 =item to_c_return_type ITEM
50 sub to_c_return_type ( $ ) {
52 return $d->{type} unless exists $d->{'posib err'};
53 return 'int' if one_of $d->{type}, ('void', 'bool', 'unsigned int');
57 =item c_error_cond ITEM
63 sub c_error_cond ( $ ) {
65 die unless exists $d->{'posib err'};
66 return '-1' if one_of $d->{type}, ('bool', 'unsigned int', 'int');
70 =item make_func NAME @TYPES PARMS ; %ACCUM
72 Creates a function prototype
76 mode: code generation mode
80 sub make_func ( $ \@ $ ; \% ) {
81 my ($name, $d, $p, $accum) = @_;
82 $accum = {} unless defined $accum;
85 (to_type_name(shift @d, {%$p,pos=>'return'}, %$accum),
89 (join ', ', map {to_type_name $_, {%$p,pos=>'parm'}, %$accum} @d),
93 =item call_func NAME @TYPES PARMS ; %ACCUM
95 Return a string to call a func. Will prefix the function with return
96 if the functions returns a non-void type;
100 mode: code generation mode
104 sub call_func ( $ \@ $ ; \% ) {
105 my ($name, $d, $p, $accum) = @_;
106 $accum = {} unless defined $accum;
108 my $func_ret = to_type_name(shift @d, {%$p,pos=>'return'}, %$accum);
110 (($func_ret eq 'void' ? '' : 'return '),
113 (join ', ', map {to_type_name $_,
114 {%$p,pos=>'parm',use_type=>false}, %$accum} @d),
118 =item to_type_name ITEM PARMS ; %ACCUM
120 Converts item into a type name.
124 mode: code generation mode
125 use_type: include the actual type
126 use_name: include the name on the type
127 pos: either "return" or "other"
131 sub to_type_name ( $ $ ; \% ) {
132 my ($d, $p, $accum) = @_;
133 $accum = {} unless defined $accum;
135 my $mode = $p->{mode};
136 die unless one_of $mode, qw(cc cc_cxx cxx native native_no_err);
137 my $is_cc = one_of $mode, qw(cc cc_cxx cxx);
138 my $is_native = one_of $mode, qw(native native_no_err);
141 my $t = finalized_type($pos eq 'return' && $is_cc
142 ? to_c_return_type $d
144 $p->{use_type} = true unless exists $p->{use_type};
145 $p->{use_name} = true unless exists $p->{use_name};
146 $p->{pos} = 'other' unless exists $p->{pos};
148 my $name = $t->{name};
149 my $type = $t->{type};
151 return ( (to_type_name {%$d, type=>'string'}, $p, %$accum) ,
152 (to_type_name {%$d, type=>'int', name=>"$d->{name}_size"}, $p, %$accum) )
153 if $name eq 'encoded string' && $is_cc && $pos eq 'parm';
159 $str .= "const " if $t->{const};
161 if ($name eq 'string') {
162 if ($is_native && $pos eq 'parm') {
163 $accum->{headers}{'parm string'} = true;
164 $str .= "ParmString";
166 $str .= "const char *";
168 } elsif ($name eq 'string obj') {
169 die unless $pos eq 'return';
171 $str .= "const char *";
173 $accum->{headers}{'string'} = true;
176 } elsif ($name eq 'encoded string') {
177 $str .= "const char *";
178 } elsif ($name eq '') {
180 } elsif ($name eq 'bool' && $is_cc) {
182 } elsif ($type eq 'basic') {
184 } elsif (one_of $type, qw(enum class struct union)) {
185 my $c_type = $type eq 'class' ? 'struct' : $type;
187 $accum->{types}->{$name} = $t;
189 $accum->{headers}->{$t->{created_in}} = true;
191 $str .= "$c_type Aspell" if $mode eq 'cc';
192 $str .= to_mixed($name);
194 print STDERR "Warning: Unknown Type: $name\n";
195 $str .= "{unknown type: $name}";
198 if ($t->{pointer} && $type eq 'class' && $mode eq 'cxx') {
200 } elsif ($t->{pointer}) {
206 if (defined $d->{name} && $p->{use_name})
208 $str .= " " unless $str eq '';
209 $str .= to_lower($d->{name});
212 $str .= "[$t->{array}]" if $t->{array} && $p->{use_type};
217 =item make_desc DESC ; LEVEL
219 Make a C comment out of DESC optionally indenting it LEVEL spaces.
223 sub make_desc ( $ ; $ ) {
224 my ($desc, $indent) = @_;
225 return '' unless defined $desc;
226 my @desc = split /\n/, $desc;
227 $indent = 0 unless defined $indent;
228 $indent = ' 'x$indent;
229 return ("$indent/* ".
230 join("\n$indent * ", @desc).
234 =item make_c_method CLASS ITEM PARMS ; %ACCUM
236 Create the phototype for a C method which is really a function.
240 mode: code generation mode
241 no_aspell: if true do not include aspell in the name
242 this_name: name for the parameter representing the current object
244 =item call_c_method CLASS ITEM PARMS ; %ACCUM
246 Like make_c_method but instead returns the appropriate string to call
247 the function. If the function returns a non-void type the string will
248 be prefixed with a return statement.
250 =item form_c_method CLASS ITEM PARMS ; %ACCUM
252 Like make_c_method except that it returns the array:
254 ($func, $data, $parms, $accum)
256 which is suitable for passing into make_func. It will return an
257 empty array if it can not make a method from ITEM.
261 sub form_c_method ($ $ $ ; \% )
263 my ($class, $d, $p, $accum) = @_;
264 $accum = {} unless defined $accum;
265 my $mode = $p->{mode};
266 my $this_name = defined $p->{this_name} ? $p->{this_name} : 'ths';
267 my $name = $d->{name};
270 @data = @{$d->{data}} if defined $d->{data};
271 if ($d->{type} eq 'constructor') {
275 $func = "new aspell $class";
277 splice @data, 0, 0, {type => $class} unless exists $d->{'returns alt type'};
278 } elsif ($d->{type} eq 'destructor') {
279 $func = "delete aspell $class";
280 splice @data, 0, 0, ({type => 'void'}, {type=>$class, name=>$this_name});
281 } elsif ($d->{type} eq 'method') {
282 if (exists $d->{'c func'}) {
283 $func = $d->{'c func'};
284 } elsif (exists $d->{'prefix'}) {
285 $func = "$d->{prefix} $name";
287 $func = "aspell $class $name";
289 if (exists $d->{'const'}) {
290 splice @data, 1, 0, {type => "const $class", name=> $this_name};
292 splice @data, 1, 0, {type => "$class", name=> $this_name};
297 $func = "aspell $func" unless $func =~ /aspell/;
298 $func =~ s/aspell\ ?// if exists $p->{no_aspell};
299 return ($func, \@data, $p, $accum);
302 sub make_c_method ($ $ $ ; \%)
304 my @ret = &form_c_method(@_);
305 return undef unless @ret > 0;
306 return &make_func(@ret);
309 sub call_c_method ($ $ $ ; \%)
311 my @ret = &form_c_method(@_);
312 return undef unless @ret > 0;
313 return &call_func(@ret);
316 =item make_cxx_method ITEM PARMS ; %ACCUM
318 Create the phototype for a C++ method.
322 mode: code generation mode
326 sub make_cxx_method ( $ $ ; \% ) {
327 my ($d, $p, $accum) = @_;
329 $ret .= make_func $d->{name}, @{$d->{data}}, $p, %$accum;
330 $ret .= " const" if exists $d->{const};