Integrate with Sarathy. perldiag.pod required manual editing.
[p5sagit/p5-mst-13.2.git] / ext / B / B / C.pm
CommitLineData
a798dbf2 1# C.pm
2#
1a52ab62 3# Copyright (c) 1996, 1997, 1998 Malcolm Beattie
a798dbf2 4#
5# You may distribute under the terms of either the GNU General Public
6# License or the Artistic License, as specified in the README file.
7#
66a2622e 8package B::C::Section;
9use B ();
10use base B::Section;
11
12sub new
13{
14 my $class = shift;
15 my $o = $class->SUPER::new(@_);
16 push(@$o,[]);
17 return $o;
18}
19
20sub add
21{
22 my $section = shift;
23 push(@{$section->[-1]},@_);
24}
25
26sub index
27{
28 my $section = shift;
29 return scalar(@{$section->[-1]})-1;
30}
31
32sub output
33{
34 my ($section, $fh, $format) = @_;
35 my $sym = $section->symtable || {};
36 my $default = $section->default;
37 foreach (@{$section->[-1]})
38 {
39 s{(s\\_[0-9a-f]+)}{ exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
40 printf $fh $format, $_;
41 }
42}
43
a798dbf2 44package B::C;
45use Exporter ();
46@ISA = qw(Exporter);
0cc1d052 47@EXPORT_OK = qw(output_all output_boilerplate output_main mark_unused
48 init_sections set_callback save_unused_subs objsym save_context);
a798dbf2 49
50use B qw(minus_c sv_undef walkoptree walksymtable main_root main_start peekop
51 class cstring cchar svref_2object compile_stats comppadlist hash
56eca212 52 threadsv_names main_cv init_av opnumber amagic_generation
b874ff32 53 AVf_REAL HEf_SVKEY);
a798dbf2 54use B::Asmdata qw(@specialsv_name);
55
56use FileHandle;
57use Carp;
58use strict;
59
60my $hv_index = 0;
61my $gv_index = 0;
62my $re_index = 0;
63my $pv_index = 0;
64my $anonsub_index = 0;
44887cfa 65my $initsub_index = 0;
a798dbf2 66
67my %symtable;
af765ed9 68my %xsub;
a798dbf2 69my $warn_undefined_syms;
70my $verbose;
66a2622e 71my %unused_sub_packages;
a798dbf2 72my $nullop_count;
66a2622e 73my $pv_copy_on_grow = 0;
a798dbf2 74my ($debug_cops, $debug_av, $debug_cv, $debug_mg);
75
76my @threadsv_names;
77BEGIN {
78 @threadsv_names = threadsv_names();
79}
80
81# Code sections
66a2622e 82my ($init, $decl, $symsect, $binopsect, $condopsect, $copsect,
a798dbf2 83 $gvopsect, $listopsect, $logopsect, $loopsect, $opsect, $pmopsect,
84 $pvopsect, $svopsect, $unopsect, $svsect, $xpvsect, $xpvavsect,
85 $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect, $xpvmgsect, $xpvlvsect,
af765ed9 86 $xrvsect, $xpvbmsect, $xpviosect );
a798dbf2 87
88sub walk_and_save_optree;
89my $saveoptree_callback = \&walk_and_save_optree;
90sub set_callback { $saveoptree_callback = shift }
91sub saveoptree { &$saveoptree_callback(@_) }
92
93sub walk_and_save_optree {
94 my ($name, $root, $start) = @_;
95 walkoptree($root, "save");
96 return objsym($start);
97}
98
99# Current workaround/fix for op_free() trying to free statically
100# defined OPs is to set op_seq = -1 and check for that in op_free().
101# Instead of hardwiring -1 in place of $op->seq, we use $op_seq
102# so that it can be changed back easily if necessary. In fact, to
103# stop compilers from moaning about a U16 being initialised with an
104# uncast -1 (the printf format is %d so we can't tweak it), we have
105# to "know" that op_seq is a U16 and use 65535. Ugh.
106my $op_seq = 65535;
107
0cc1d052 108# Look this up here so we can do just a number compare
109# rather than looking up the name of every BASEOP in B::OP
110my $OP_THREADSV = opnumber('threadsv');
a798dbf2 111
112sub savesym {
113 my ($obj, $value) = @_;
114 my $sym = sprintf("s\\_%x", $$obj);
115 $symtable{$sym} = $value;
116}
117
118sub objsym {
119 my $obj = shift;
120 return $symtable{sprintf("s\\_%x", $$obj)};
121}
122
123sub getsym {
124 my $sym = shift;
125 my $value;
126
127 return 0 if $sym eq "sym_0"; # special case
128 $value = $symtable{$sym};
129 if (defined($value)) {
130 return $value;
131 } else {
132 warn "warning: undefined symbol $sym\n" if $warn_undefined_syms;
133 return "UNUSED";
134 }
135}
136
137sub savepv {
66a2622e 138 my $pv = shift;
139 $pv = '' unless defined $pv; # Is this sane ?
a798dbf2 140 my $pvsym = 0;
141 my $pvmax = 0;
66a2622e 142 if ($pv_copy_on_grow) {
a798dbf2 143 my $cstring = cstring($pv);
144 if ($cstring ne "0") { # sic
145 $pvsym = sprintf("pv%d", $pv_index++);
146 $decl->add(sprintf("static char %s[] = %s;", $pvsym, $cstring));
147 }
148 } else {
149 $pvmax = length($pv) + 1;
150 }
151 return ($pvsym, $pvmax);
152}
153
154sub B::OP::save {
155 my ($op, $level) = @_;
2c0b28dd 156 my $sym = objsym($op);
157 return $sym if defined $sym;
a798dbf2 158 my $type = $op->type;
159 $nullop_count++ unless $type;
0cc1d052 160 if ($type == $OP_THREADSV) {
a798dbf2 161 # saves looking up ppaddr but it's a bit naughty to hard code this
162 $init->add(sprintf("(void)find_threadsv(%s);",
163 cstring($threadsv_names[$op->targ])));
164 }
165 $opsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x",
166 ${$op->next}, ${$op->sibling}, $op->ppaddr, $op->targ,
167 $type, $op_seq, $op->flags, $op->private));
168 savesym($op, sprintf("&op_list[%d]", $opsect->index));
169}
170
171sub B::FAKEOP::new {
172 my ($class, %objdata) = @_;
173 bless \%objdata, $class;
174}
175
176sub B::FAKEOP::save {
177 my ($op, $level) = @_;
178 $opsect->add(sprintf("%s, %s, %s, %u, %u, %u, 0x%x, 0x%x",
179 $op->next, $op->sibling, $op->ppaddr, $op->targ,
180 $op->type, $op_seq, $op->flags, $op->private));
181 return sprintf("&op_list[%d]", $opsect->index);
182}
183
184sub B::FAKEOP::next { $_[0]->{"next"} || 0 }
185sub B::FAKEOP::type { $_[0]->{type} || 0}
186sub B::FAKEOP::sibling { $_[0]->{sibling} || 0 }
187sub B::FAKEOP::ppaddr { $_[0]->{ppaddr} || 0 }
188sub B::FAKEOP::targ { $_[0]->{targ} || 0 }
189sub B::FAKEOP::flags { $_[0]->{flags} || 0 }
190sub B::FAKEOP::private { $_[0]->{private} || 0 }
191
192sub B::UNOP::save {
193 my ($op, $level) = @_;
2c0b28dd 194 my $sym = objsym($op);
195 return $sym if defined $sym;
a798dbf2 196 $unopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x",
197 ${$op->next}, ${$op->sibling}, $op->ppaddr,
198 $op->targ, $op->type, $op_seq, $op->flags,
199 $op->private, ${$op->first}));
200 savesym($op, sprintf("(OP*)&unop_list[%d]", $unopsect->index));
201}
202
203sub B::BINOP::save {
204 my ($op, $level) = @_;
2c0b28dd 205 my $sym = objsym($op);
206 return $sym if defined $sym;
a798dbf2 207 $binopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
208 ${$op->next}, ${$op->sibling}, $op->ppaddr,
209 $op->targ, $op->type, $op_seq, $op->flags,
210 $op->private, ${$op->first}, ${$op->last}));
211 savesym($op, sprintf("(OP*)&binop_list[%d]", $binopsect->index));
212}
213
214sub B::LISTOP::save {
215 my ($op, $level) = @_;
2c0b28dd 216 my $sym = objsym($op);
217 return $sym if defined $sym;
a798dbf2 218 $listopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u",
219 ${$op->next}, ${$op->sibling}, $op->ppaddr,
220 $op->targ, $op->type, $op_seq, $op->flags,
221 $op->private, ${$op->first}, ${$op->last},
222 $op->children));
223 savesym($op, sprintf("(OP*)&listop_list[%d]", $listopsect->index));
224}
225
226sub B::LOGOP::save {
227 my ($op, $level) = @_;
2c0b28dd 228 my $sym = objsym($op);
229 return $sym if defined $sym;
a798dbf2 230 $logopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
231 ${$op->next}, ${$op->sibling}, $op->ppaddr,
232 $op->targ, $op->type, $op_seq, $op->flags,
233 $op->private, ${$op->first}, ${$op->other}));
234 savesym($op, sprintf("(OP*)&logop_list[%d]", $logopsect->index));
235}
236
a798dbf2 237sub B::LOOP::save {
238 my ($op, $level) = @_;
2c0b28dd 239 my $sym = objsym($op);
240 return $sym if defined $sym;
a798dbf2 241 #warn sprintf("LOOP: redoop %s, nextop %s, lastop %s\n",
242 # peekop($op->redoop), peekop($op->nextop),
243 # peekop($op->lastop)); # debug
244 $loopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, s\\_%x, s\\_%x, s\\_%x",
245 ${$op->next}, ${$op->sibling}, $op->ppaddr,
246 $op->targ, $op->type, $op_seq, $op->flags,
247 $op->private, ${$op->first}, ${$op->last},
248 $op->children, ${$op->redoop}, ${$op->nextop},
249 ${$op->lastop}));
250 savesym($op, sprintf("(OP*)&loop_list[%d]", $loopsect->index));
251}
252
253sub B::PVOP::save {
254 my ($op, $level) = @_;
2c0b28dd 255 my $sym = objsym($op);
256 return $sym if defined $sym;
a798dbf2 257 $pvopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s",
258 ${$op->next}, ${$op->sibling}, $op->ppaddr,
259 $op->targ, $op->type, $op_seq, $op->flags,
260 $op->private, cstring($op->pv)));
261 savesym($op, sprintf("(OP*)&pvop_list[%d]", $pvopsect->index));
262}
263
264sub B::SVOP::save {
265 my ($op, $level) = @_;
2c0b28dd 266 my $sym = objsym($op);
267 return $sym if defined $sym;
a798dbf2 268 my $svsym = $op->sv->save;
269 $svopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s",
270 ${$op->next}, ${$op->sibling}, $op->ppaddr,
271 $op->targ, $op->type, $op_seq, $op->flags,
272 $op->private, "(SV*)$svsym"));
273 savesym($op, sprintf("(OP*)&svop_list[%d]", $svopsect->index));
274}
275
276sub B::GVOP::save {
277 my ($op, $level) = @_;
2c0b28dd 278 my $sym = objsym($op);
279 return $sym if defined $sym;
a798dbf2 280 my $gvsym = $op->gv->save;
281 $gvopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, Nullgv",
282 ${$op->next}, ${$op->sibling}, $op->ppaddr,
283 $op->targ, $op->type, $op_seq, $op->flags,
284 $op->private));
285 $init->add(sprintf("gvop_list[%d].op_gv = %s;", $gvopsect->index, $gvsym));
286 savesym($op, sprintf("(OP*)&gvop_list[%d]", $gvopsect->index));
287}
288
289sub B::COP::save {
290 my ($op, $level) = @_;
2c0b28dd 291 my $sym = objsym($op);
292 return $sym if defined $sym;
a798dbf2 293 my $gvsym = $op->filegv->save;
294 my $stashsym = $op->stash->save;
295 warn sprintf("COP: line %d file %s\n", $op->line, $op->filegv->SV->PV)
296 if $debug_cops;
297 $copsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s, Nullhv, Nullgv, %u, %d, %u",
298 ${$op->next}, ${$op->sibling}, $op->ppaddr,
299 $op->targ, $op->type, $op_seq, $op->flags,
300 $op->private, cstring($op->label), $op->cop_seq,
301 $op->arybase, $op->line));
302 my $copix = $copsect->index;
303 $init->add(sprintf("cop_list[%d].cop_filegv = %s;", $copix, $gvsym),
304 sprintf("cop_list[%d].cop_stash = %s;", $copix, $stashsym));
305 savesym($op, "(OP*)&cop_list[$copix]");
306}
307
308sub B::PMOP::save {
309 my ($op, $level) = @_;
2c0b28dd 310 my $sym = objsym($op);
311 return $sym if defined $sym;
a798dbf2 312 my $replroot = $op->pmreplroot;
313 my $replstart = $op->pmreplstart;
314 my $replrootfield = sprintf("s\\_%x", $$replroot);
315 my $replstartfield = sprintf("s\\_%x", $$replstart);
316 my $gvsym;
317 my $ppaddr = $op->ppaddr;
318 if ($$replroot) {
319 # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
320 # argument to a split) stores a GV in op_pmreplroot instead
321 # of a substitution syntax tree. We don't want to walk that...
322 if ($ppaddr eq "pp_pushre") {
323 $gvsym = $replroot->save;
324# warn "PMOP::save saving a pp_pushre with GV $gvsym\n"; # debug
325 $replrootfield = 0;
326 } else {
327 $replstartfield = saveoptree("*ignore*", $replroot, $replstart);
328 }
329 }
330 # pmnext handling is broken in perl itself, I think. Bad op_pmnext
331 # fields aren't noticed in perl's runtime (unless you try reset) but we
332 # segfault when trying to dereference it to find op->op_pmnext->op_type
333 $pmopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, %s, %s, 0, 0, 0x%x, 0x%x",
334 ${$op->next}, ${$op->sibling}, $ppaddr, $op->targ,
335 $op->type, $op_seq, $op->flags, $op->private,
336 ${$op->first}, ${$op->last}, $op->children,
337 $replrootfield, $replstartfield,
338 $op->pmflags, $op->pmpermflags,));
339 my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
340 my $re = $op->precomp;
341 if (defined($re)) {
342 my $resym = sprintf("re%d", $re_index++);
343 $decl->add(sprintf("static char *$resym = %s;", cstring($re)));
344 $init->add(sprintf("$pm.op_pmregexp = pregcomp($resym, $resym + %u, &$pm);",
345 length($re)));
346 }
347 if ($gvsym) {
348 $init->add("$pm.op_pmreplroot = (OP*)$gvsym;");
349 }
350 savesym($op, sprintf("(OP*)&pmop_list[%d]", $pmopsect->index));
351}
352
353sub B::SPECIAL::save {
354 my ($sv) = @_;
355 # special case: $$sv is not the address but an index into specialsv_list
356# warn "SPECIAL::save specialsv $$sv\n"; # debug
357 my $sym = $specialsv_name[$$sv];
358 if (!defined($sym)) {
359 confess "unknown specialsv index $$sv passed to B::SPECIAL::save";
360 }
361 return $sym;
362}
363
364sub B::OBJECT::save {}
365
366sub B::NULL::save {
367 my ($sv) = @_;
368 my $sym = objsym($sv);
369 return $sym if defined $sym;
370# warn "Saving SVt_NULL SV\n"; # debug
371 # debug
372 #if ($$sv == 0) {
373 # warn "NULL::save for sv = 0 called from @{[(caller(1))[3]]}\n";
374 #}
375 $svsect->add(sprintf("0, %u, 0x%x", $sv->REFCNT + 1, $sv->FLAGS));
376 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
377}
378
379sub B::IV::save {
380 my ($sv) = @_;
381 my $sym = objsym($sv);
382 return $sym if defined $sym;
383 $xpvivsect->add(sprintf("0, 0, 0, %d", $sv->IVX));
384 $svsect->add(sprintf("&xpviv_list[%d], %lu, 0x%x",
385 $xpvivsect->index, $sv->REFCNT + 1, $sv->FLAGS));
386 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
387}
388
389sub B::NV::save {
390 my ($sv) = @_;
391 my $sym = objsym($sv);
392 return $sym if defined $sym;
56eca212 393 my $val= $sv->NVX;
394 $val .= '.00' if $val =~ /^-?\d+$/;
395 $xpvnvsect->add(sprintf("0, 0, 0, %d, %s", $sv->IVX, $val));
a798dbf2 396 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
397 $xpvnvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
398 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
399}
400
401sub B::PVLV::save {
402 my ($sv) = @_;
403 my $sym = objsym($sv);
404 return $sym if defined $sym;
405 my $pv = $sv->PV;
406 my $len = length($pv);
407 my ($pvsym, $pvmax) = savepv($pv);
408 my ($lvtarg, $lvtarg_sym);
409 $xpvlvsect->add(sprintf("%s, %u, %u, %d, %g, 0, 0, %u, %u, 0, %s",
410 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX,
411 $sv->TARGOFF, $sv->TARGLEN, cchar($sv->TYPE)));
412 $svsect->add(sprintf("&xpvlv_list[%d], %lu, 0x%x",
413 $xpvlvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
414 if (!$pv_copy_on_grow) {
415 $init->add(sprintf("xpvlv_list[%d].xpv_pv = savepvn(%s, %u);",
416 $xpvlvsect->index, cstring($pv), $len));
417 }
418 $sv->save_magic;
419 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
420}
421
422sub B::PVIV::save {
423 my ($sv) = @_;
424 my $sym = objsym($sv);
425 return $sym if defined $sym;
426 my $pv = $sv->PV;
427 my $len = length($pv);
428 my ($pvsym, $pvmax) = savepv($pv);
429 $xpvivsect->add(sprintf("%s, %u, %u, %d", $pvsym, $len, $pvmax, $sv->IVX));
430 $svsect->add(sprintf("&xpviv_list[%d], %u, 0x%x",
431 $xpvivsect->index, $sv->REFCNT + 1, $sv->FLAGS));
432 if (!$pv_copy_on_grow) {
433 $init->add(sprintf("xpviv_list[%d].xpv_pv = savepvn(%s, %u);",
434 $xpvivsect->index, cstring($pv), $len));
435 }
436 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
437}
438
439sub B::PVNV::save {
440 my ($sv) = @_;
441 my $sym = objsym($sv);
442 return $sym if defined $sym;
66a2622e 443 my $pv = $sv->PV;
444 $pv = '' unless defined $pv;
a798dbf2 445 my $len = length($pv);
446 my ($pvsym, $pvmax) = savepv($pv);
56eca212 447 my $val= $sv->NVX;
448 $val .= '.00' if $val =~ /^-?\d+$/;
a798dbf2 449 $xpvnvsect->add(sprintf("%s, %u, %u, %d, %s",
56eca212 450 $pvsym, $len, $pvmax, $sv->IVX, $val));
a798dbf2 451 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
452 $xpvnvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
453 if (!$pv_copy_on_grow) {
454 $init->add(sprintf("xpvnv_list[%d].xpv_pv = savepvn(%s,%u);",
455 $xpvnvsect->index, cstring($pv), $len));
456 }
457 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
458}
459
460sub B::BM::save {
461 my ($sv) = @_;
462 my $sym = objsym($sv);
463 return $sym if defined $sym;
464 my $pv = $sv->PV . "\0" . $sv->TABLE;
465 my $len = length($pv);
466 $xpvbmsect->add(sprintf("0, %u, %u, %d, %s, 0, 0, %d, %u, 0x%x",
467 $len, $len + 258, $sv->IVX, $sv->NVX,
468 $sv->USEFUL, $sv->PREVIOUS, $sv->RARE));
469 $svsect->add(sprintf("&xpvbm_list[%d], %lu, 0x%x",
470 $xpvbmsect->index, $sv->REFCNT + 1, $sv->FLAGS));
471 $sv->save_magic;
472 $init->add(sprintf("xpvbm_list[%d].xpv_pv = savepvn(%s, %u);",
473 $xpvbmsect->index, cstring($pv), $len),
474 sprintf("xpvbm_list[%d].xpv_cur = %u;",
475 $xpvbmsect->index, $len - 257));
476 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
477}
478
479sub B::PV::save {
480 my ($sv) = @_;
481 my $sym = objsym($sv);
482 return $sym if defined $sym;
483 my $pv = $sv->PV;
484 my $len = length($pv);
485 my ($pvsym, $pvmax) = savepv($pv);
486 $xpvsect->add(sprintf("%s, %u, %u", $pvsym, $len, $pvmax));
487 $svsect->add(sprintf("&xpv_list[%d], %lu, 0x%x",
488 $xpvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
489 if (!$pv_copy_on_grow) {
490 $init->add(sprintf("xpv_list[%d].xpv_pv = savepvn(%s, %u);",
491 $xpvsect->index, cstring($pv), $len));
492 }
493 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
494}
495
496sub B::PVMG::save {
497 my ($sv) = @_;
498 my $sym = objsym($sv);
499 return $sym if defined $sym;
500 my $pv = $sv->PV;
501 my $len = length($pv);
502 my ($pvsym, $pvmax) = savepv($pv);
503 $xpvmgsect->add(sprintf("%s, %u, %u, %d, %s, 0, 0",
504 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX));
505 $svsect->add(sprintf("&xpvmg_list[%d], %lu, 0x%x",
506 $xpvmgsect->index, $sv->REFCNT + 1, $sv->FLAGS));
507 if (!$pv_copy_on_grow) {
508 $init->add(sprintf("xpvmg_list[%d].xpv_pv = savepvn(%s, %u);",
509 $xpvmgsect->index, cstring($pv), $len));
510 }
511 $sym = savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
512 $sv->save_magic;
513 return $sym;
514}
515
516sub B::PVMG::save_magic {
517 my ($sv) = @_;
518 #warn sprintf("saving magic for %s (0x%x)\n", class($sv), $$sv); # debug
519 my $stash = $sv->SvSTASH;
56eca212 520 $stash->save;
a798dbf2 521 if ($$stash) {
522 warn sprintf("xmg_stash = %s (0x%x)\n", $stash->NAME, $$stash)
523 if $debug_mg;
524 # XXX Hope stash is already going to be saved.
525 $init->add(sprintf("SvSTASH(s\\_%x) = s\\_%x;", $$sv, $$stash));
526 }
527 my @mgchain = $sv->MAGIC;
88b39979 528 my ($mg, $type, $obj, $ptr,$len,$ptrsv);
a798dbf2 529 foreach $mg (@mgchain) {
530 $type = $mg->TYPE;
531 $obj = $mg->OBJ;
532 $ptr = $mg->PTR;
88b39979 533 $len=$mg->LENGTH;
a798dbf2 534 if ($debug_mg) {
535 warn sprintf("magic %s (0x%x), obj %s (0x%x), type %s, ptr %s\n",
536 class($sv), $$sv, class($obj), $$obj,
537 cchar($type), cstring($ptr));
538 }
56eca212 539 $obj->save;
88b39979 540 if ($len == HEf_SVKEY){
541 #The pointer is an SV*
542 $ptrsv=svref_2object($ptr)->save;
5ab5c7a4 543 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s,(char *) %s, %d);",
88b39979 544 $$sv, $$obj, cchar($type),$ptrsv,$len));
545 }else{
546 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
a798dbf2 547 $$sv, $$obj, cchar($type),cstring($ptr),$len));
88b39979 548 }
a798dbf2 549 }
550}
551
552sub B::RV::save {
553 my ($sv) = @_;
554 my $sym = objsym($sv);
555 return $sym if defined $sym;
66a2622e 556 my $rv = $sv->RV->save;
557 $rv =~ s/^\([AGHS]V\s*\*\)\s*(\&sv_list.*)$/$1/;
558 $xrvsect->add($rv);
a798dbf2 559 $svsect->add(sprintf("&xrv_list[%d], %lu, 0x%x",
560 $xrvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
561 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
562}
563
564sub try_autoload {
565 my ($cvstashname, $cvname) = @_;
566 warn sprintf("No definition for sub %s::%s\n", $cvstashname, $cvname);
567 # Handle AutoLoader classes explicitly. Any more general AUTOLOAD
568 # use should be handled by the class itself.
569 no strict 'refs';
570 my $isa = \@{"$cvstashname\::ISA"};
571 if (grep($_ eq "AutoLoader", @$isa)) {
572 warn "Forcing immediate load of sub derived from AutoLoader\n";
573 # Tweaked version of AutoLoader::AUTOLOAD
574 my $dir = $cvstashname;
575 $dir =~ s(::)(/)g;
576 eval { require "auto/$dir/$cvname.al" };
577 if ($@) {
578 warn qq(failed require "auto/$dir/$cvname.al": $@\n);
579 return 0;
580 } else {
581 return 1;
582 }
583 }
584}
585
586sub B::CV::save {
587 my ($cv) = @_;
588 my $sym = objsym($cv);
589 if (defined($sym)) {
590# warn sprintf("CV 0x%x already saved as $sym\n", $$cv); # debug
591 return $sym;
592 }
593 # Reserve a place in svsect and xpvcvsect and record indices
af765ed9 594 my $gv = $cv->GV;
595 my $cvstashname = $gv->STASH->NAME;
596 my $cvname = $gv->NAME;
597 my $root = $cv->ROOT;
598 my $cvxsub = $cv->XSUB;
599 if ($cvxsub) {
600 my $egv = $gv->EGV;
601 my $stashname = $egv->STASH->NAME;
602 $xsub{$stashname}='Static' unless $xsub{$stashname};
603 }
a798dbf2 604 my $sv_ix = $svsect->index + 1;
605 $svsect->add("svix$sv_ix");
606 my $xpvcv_ix = $xpvcvsect->index + 1;
607 $xpvcvsect->add("xpvcvix$xpvcv_ix");
608 # Save symbol now so that GvCV() doesn't recurse back to us via CvGV()
609 $sym = savesym($cv, "&sv_list[$sv_ix]");
610 warn sprintf("saving CV 0x%x as $sym\n", $$cv) if $debug_cv;
a798dbf2 611 if (!$$root && !$cvxsub) {
612 if (try_autoload($cvstashname, $cvname)) {
613 # Recalculate root and xsub
614 $root = $cv->ROOT;
615 $cvxsub = $cv->XSUB;
616 if ($$root || $cvxsub) {
617 warn "Successful forced autoload\n";
618 }
619 }
620 }
621 my $startfield = 0;
622 my $padlist = $cv->PADLIST;
623 my $pv = $cv->PV;
624 my $xsub = 0;
625 my $xsubany = "Nullany";
626 if ($$root) {
627 warn sprintf("saving op tree for CV 0x%x, root = 0x%x\n",
628 $$cv, $$root) if $debug_cv;
629 my $ppname = "";
630 if ($$gv) {
631 my $stashname = $gv->STASH->NAME;
632 my $gvname = $gv->NAME;
633 if ($gvname ne "__ANON__") {
634 $ppname = (${$gv->FORM} == $$cv) ? "pp_form_" : "pp_sub_";
635 $ppname .= ($stashname eq "main") ?
636 $gvname : "$stashname\::$gvname";
637 $ppname =~ s/::/__/g;
44887cfa 638 if ($gvname eq "INIT"){
639 $ppname .= "_$initsub_index";
640 $initsub_index++;
641 }
a798dbf2 642 }
643 }
644 if (!$ppname) {
645 $ppname = "pp_anonsub_$anonsub_index";
646 $anonsub_index++;
647 }
648 $startfield = saveoptree($ppname, $root, $cv->START, $padlist->ARRAY);
649 warn sprintf("done saving op tree for CV 0x%x, name %s, root 0x%x\n",
650 $$cv, $ppname, $$root) if $debug_cv;
651 if ($$padlist) {
652 warn sprintf("saving PADLIST 0x%x for CV 0x%x\n",
653 $$padlist, $$cv) if $debug_cv;
654 $padlist->save;
655 warn sprintf("done saving PADLIST 0x%x for CV 0x%x\n",
656 $$padlist, $$cv) if $debug_cv;
657 }
658 }
a798dbf2 659 else {
660 warn sprintf("No definition for sub %s::%s (unable to autoload)\n",
661 $cvstashname, $cvname); # debug
66a2622e 662 }
663 $pv = '' unless defined $pv; # Avoid use of undef warnings
5cfd8ad4 664 $symsect->add(sprintf("xpvcvix%d\t%s, %u, 0, %d, %s, 0, Nullhv, Nullhv, %s, s\\_%x, $xsub, $xsubany, Nullgv, Nullgv, %d, s\\_%x, (CV*)s\\_%x, 0x%x",
a798dbf2 665 $xpvcv_ix, cstring($pv), length($pv), $cv->IVX,
666 $cv->NVX, $startfield, ${$cv->ROOT}, $cv->DEPTH,
5cfd8ad4 667 $$padlist, ${$cv->OUTSIDE}, $cv->CvFLAGS));
668
669 if (${$cv->OUTSIDE} == ${main_cv()}){
670 $init->add(sprintf("CvOUTSIDE(s\\_%x)=PL_main_cv;",$$cv));
358b5eb8 671 $init->add(sprintf("SvREFCNT_inc(PL_main_cv);"));
5cfd8ad4 672 }
673
a798dbf2 674 if ($$gv) {
675 $gv->save;
676 $init->add(sprintf("CvGV(s\\_%x) = s\\_%x;",$$cv,$$gv));
677 warn sprintf("done saving GV 0x%x for CV 0x%x\n",
678 $$gv, $$cv) if $debug_cv;
679 }
680 my $filegv = $cv->FILEGV;
681 if ($$filegv) {
682 $filegv->save;
683 $init->add(sprintf("CvFILEGV(s\\_%x) = s\\_%x;", $$cv, $$filegv));
684 warn sprintf("done saving FILEGV 0x%x for CV 0x%x\n",
685 $$filegv, $$cv) if $debug_cv;
686 }
687 my $stash = $cv->STASH;
688 if ($$stash) {
689 $stash->save;
690 $init->add(sprintf("CvSTASH(s\\_%x) = s\\_%x;", $$cv, $$stash));
691 warn sprintf("done saving STASH 0x%x for CV 0x%x\n",
692 $$stash, $$cv) if $debug_cv;
693 }
694 $symsect->add(sprintf("svix%d\t(XPVCV*)&xpvcv_list[%u], %lu, 0x%x",
695 $sv_ix, $xpvcv_ix, $cv->REFCNT + 1, $cv->FLAGS));
696 return $sym;
697}
698
699sub B::GV::save {
7cf11ee8 700 my ($gv,$skip_cv) = @_;
a798dbf2 701 my $sym = objsym($gv);
702 if (defined($sym)) {
703 #warn sprintf("GV 0x%x already saved as $sym\n", $$gv); # debug
704 return $sym;
705 } else {
706 my $ix = $gv_index++;
707 $sym = savesym($gv, "gv_list[$ix]");
708 #warn sprintf("Saving GV 0x%x as $sym\n", $$gv); # debug
709 }
710 my $gvname = $gv->NAME;
711 my $name = cstring($gv->STASH->NAME . "::" . $gvname);
712 #warn "GV name is $name\n"; # debug
713 my $egv = $gv->EGV;
714 my $egvsym;
715 if ($$gv != $$egv) {
716 #warn(sprintf("EGV name is %s, saving it now\n",
717 # $egv->STASH->NAME . "::" . $egv->NAME)); # debug
718 $egvsym = $egv->save;
719 }
720 $init->add(qq[$sym = gv_fetchpv($name, TRUE, SVt_PV);],
721 sprintf("SvFLAGS($sym) = 0x%x;", $gv->FLAGS),
722 sprintf("GvFLAGS($sym) = 0x%x;", $gv->GvFLAGS),
723 sprintf("GvLINE($sym) = %u;", $gv->LINE));
724 # Shouldn't need to do save_magic since gv_fetchpv handles that
725 #$gv->save_magic;
726 my $refcnt = $gv->REFCNT + 1;
727 $init->add(sprintf("SvREFCNT($sym) += %u;", $refcnt - 1)) if $refcnt > 1;
728 my $gvrefcnt = $gv->GvREFCNT;
729 if ($gvrefcnt > 1) {
730 $init->add(sprintf("GvREFCNT($sym) += %u;", $gvrefcnt - 1));
731 }
732 if (defined($egvsym)) {
733 # Shared glob *foo = *bar
734 $init->add("gp_free($sym);",
735 "GvGP($sym) = GvGP($egvsym);");
736 } elsif ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) {
737 # Don't save subfields of special GVs (*_, *1, *# and so on)
738# warn "GV::save saving subfields\n"; # debug
739 my $gvsv = $gv->SV;
740 if ($$gvsv) {
cfa4c8ee 741 $gvsv->save;
a798dbf2 742 $init->add(sprintf("GvSV($sym) = s\\_%x;", $$gvsv));
743# warn "GV::save \$$name\n"; # debug
a798dbf2 744 }
745 my $gvav = $gv->AV;
746 if ($$gvav) {
cfa4c8ee 747 $gvav->save;
a798dbf2 748 $init->add(sprintf("GvAV($sym) = s\\_%x;", $$gvav));
749# warn "GV::save \@$name\n"; # debug
a798dbf2 750 }
751 my $gvhv = $gv->HV;
752 if ($$gvhv) {
cfa4c8ee 753 $gvhv->save;
a798dbf2 754 $init->add(sprintf("GvHV($sym) = s\\_%x;", $$gvhv));
755# warn "GV::save \%$name\n"; # debug
a798dbf2 756 }
757 my $gvcv = $gv->CV;
af765ed9 758 if ($$gvcv && !$skip_cv && !$gvcv->XSUB) { #not XSUB
759 $gvcv->save;
760 $init->add(sprintf("GvCV($sym) = (CV*)s\\_%x;", $$gvcv));
761# warn "GV::save &$name\n"; # debug
762 }elsif ($$gvcv && $gvcv->XSUB && $name ne
763 (my $origname=cstring($gvcv->GV->EGV->STASH->NAME .
764 "::" . $gvcv->GV->EGV->NAME))) { #XSUB alias
765
766 $init->add("{ CV *cv;");
767 $init->add("\tcv=GvCV(gv_fetchpv($origname,FALSE,SVt_PV));");
768 $init->add("\tGvCV($sym)=cv;");
769 $init->add("\tSvREFCNT_inc((SV *)cv);");
770 $init->add("}");
771
772 }
a798dbf2 773 my $gvfilegv = $gv->FILEGV;
774 if ($$gvfilegv) {
cfa4c8ee 775 $gvfilegv->save;
5ed82aed 776 $init->add(sprintf("GvFILEGV($sym) = (GV*)s\\_%x;",$$gvfilegv));
a798dbf2 777# warn "GV::save GvFILEGV(*$name)\n"; # debug
a798dbf2 778 }
779 my $gvform = $gv->FORM;
780 if ($$gvform) {
cfa4c8ee 781 $gvform->save;
a798dbf2 782 $init->add(sprintf("GvFORM($sym) = (CV*)s\\_%x;", $$gvform));
783# warn "GV::save GvFORM(*$name)\n"; # debug
a798dbf2 784 }
785 my $gvio = $gv->IO;
786 if ($$gvio) {
cfa4c8ee 787 $gvio->save;
a798dbf2 788 $init->add(sprintf("GvIOp($sym) = s\\_%x;", $$gvio));
789# warn "GV::save GvIO(*$name)\n"; # debug
a798dbf2 790 }
791 }
792 return $sym;
793}
794sub B::AV::save {
795 my ($av) = @_;
796 my $sym = objsym($av);
797 return $sym if defined $sym;
798 my $avflags = $av->AvFLAGS;
799 $xpvavsect->add(sprintf("0, -1, -1, 0, 0.0, 0, Nullhv, 0, 0, 0x%x",
800 $avflags));
801 $svsect->add(sprintf("&xpvav_list[%d], %lu, 0x%x",
802 $xpvavsect->index, $av->REFCNT + 1, $av->FLAGS));
803 my $sv_list_index = $svsect->index;
804 my $fill = $av->FILL;
805 $av->save_magic;
806 warn sprintf("saving AV 0x%x FILL=$fill AvFLAGS=0x%x", $$av, $avflags)
807 if $debug_av;
808 # XXX AVf_REAL is wrong test: need to save comppadlist but not stack
809 #if ($fill > -1 && ($avflags & AVf_REAL)) {
810 if ($fill > -1) {
811 my @array = $av->ARRAY;
812 if ($debug_av) {
813 my $el;
814 my $i = 0;
815 foreach $el (@array) {
816 warn sprintf("AV 0x%x[%d] = %s 0x%x\n",
817 $$av, $i++, class($el), $$el);
818 }
819 }
820 my @names = map($_->save, @array);
821 # XXX Better ways to write loop?
822 # Perhaps svp[0] = ...; svp[1] = ...; svp[2] = ...;
823 # Perhaps I32 i = 0; svp[i++] = ...; svp[i++] = ...; svp[i++] = ...;
824 $init->add("{",
825 "\tSV **svp;",
826 "\tAV *av = (AV*)&sv_list[$sv_list_index];",
827 "\tav_extend(av, $fill);",
828 "\tsvp = AvARRAY(av);",
829 map("\t*svp++ = (SV*)$_;", @names),
830 "\tAvFILLp(av) = $fill;",
831 "}");
832 } else {
833 my $max = $av->MAX;
834 $init->add("av_extend((AV*)&sv_list[$sv_list_index], $max);")
835 if $max > -1;
836 }
837 return savesym($av, "(AV*)&sv_list[$sv_list_index]");
838}
839
840sub B::HV::save {
841 my ($hv) = @_;
842 my $sym = objsym($hv);
843 return $sym if defined $sym;
844 my $name = $hv->NAME;
845 if ($name) {
846 # It's a stash
847
848 # A perl bug means HvPMROOT isn't altered when a PMOP is freed. Usually
849 # the only symptom is that sv_reset tries to reset the PMf_USED flag of
850 # a trashed op but we look at the trashed op_type and segfault.
851 #my $adpmroot = ${$hv->PMROOT};
852 my $adpmroot = 0;
853 $decl->add("static HV *hv$hv_index;");
854 # XXX Beware of weird package names containing double-quotes, \n, ...?
855 $init->add(qq[hv$hv_index = gv_stashpv("$name", TRUE);]);
856 if ($adpmroot) {
857 $init->add(sprintf("HvPMROOT(hv$hv_index) = (PMOP*)s\\_%x;",
858 $adpmroot));
859 }
860 $sym = savesym($hv, "hv$hv_index");
861 $hv_index++;
862 return $sym;
863 }
864 # It's just an ordinary HV
865 $xpvhvsect->add(sprintf("0, 0, %d, 0, 0.0, 0, Nullhv, %d, 0, 0, 0",
866 $hv->MAX, $hv->RITER));
867 $svsect->add(sprintf("&xpvhv_list[%d], %lu, 0x%x",
868 $xpvhvsect->index, $hv->REFCNT + 1, $hv->FLAGS));
869 my $sv_list_index = $svsect->index;
870 my @contents = $hv->ARRAY;
871 if (@contents) {
872 my $i;
873 for ($i = 1; $i < @contents; $i += 2) {
874 $contents[$i] = $contents[$i]->save;
875 }
876 $init->add("{", "\tHV *hv = (HV*)&sv_list[$sv_list_index];");
877 while (@contents) {
878 my ($key, $value) = splice(@contents, 0, 2);
879 $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
880 cstring($key),length($key),$value, hash($key)));
cf86991c 881# $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
882# cstring($key),length($key),$value, 0));
a798dbf2 883 }
884 $init->add("}");
885 }
56eca212 886 $hv->save_magic();
a798dbf2 887 return savesym($hv, "(HV*)&sv_list[$sv_list_index]");
888}
889
890sub B::IO::save {
891 my ($io) = @_;
892 my $sym = objsym($io);
893 return $sym if defined $sym;
894 my $pv = $io->PV;
66a2622e 895 $pv = '' unless defined $pv;
a798dbf2 896 my $len = length($pv);
897 $xpviosect->add(sprintf("0, %u, %u, %d, %s, 0, 0, 0, 0, 0, %d, %d, %d, %d, %s, Nullgv, %s, Nullgv, %s, Nullgv, %d, %s, 0x%x",
898 $len, $len+1, $io->IVX, $io->NVX, $io->LINES,
899 $io->PAGE, $io->PAGE_LEN, $io->LINES_LEFT,
900 cstring($io->TOP_NAME), cstring($io->FMT_NAME),
901 cstring($io->BOTTOM_NAME), $io->SUBPROCESS,
902 cchar($io->IoTYPE), $io->IoFLAGS));
903 $svsect->add(sprintf("&xpvio_list[%d], %lu, 0x%x",
904 $xpviosect->index, $io->REFCNT + 1, $io->FLAGS));
905 $sym = savesym($io, sprintf("(IO*)&sv_list[%d]", $svsect->index));
906 my ($field, $fsym);
907 foreach $field (qw(TOP_GV FMT_GV BOTTOM_GV)) {
908 $fsym = $io->$field();
909 if ($$fsym) {
910 $init->add(sprintf("Io$field($sym) = (GV*)s\\_%x;", $$fsym));
911 $fsym->save;
912 }
913 }
914 $io->save_magic;
915 return $sym;
916}
917
918sub B::SV::save {
919 my $sv = shift;
920 # This is where we catch an honest-to-goodness Nullsv (which gets
921 # blessed into B::SV explicitly) and any stray erroneous SVs.
922 return 0 unless $$sv;
923 confess sprintf("cannot save that type of SV: %s (0x%x)\n",
924 class($sv), $$sv);
925}
926
927sub output_all {
928 my $init_name = shift;
929 my $section;
930 my @sections = ($opsect, $unopsect, $binopsect, $logopsect, $condopsect,
931 $listopsect, $pmopsect, $svopsect, $gvopsect, $pvopsect,
66a2622e 932 $loopsect, $copsect, $svsect, $xpvsect,
a798dbf2 933 $xpvavsect, $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect,
934 $xpvmgsect, $xpvlvsect, $xrvsect, $xpvbmsect, $xpviosect);
935 $symsect->output(\*STDOUT, "#define %s\n");
936 print "\n";
937 output_declarations();
938 foreach $section (@sections) {
939 my $lines = $section->index + 1;
940 if ($lines) {
941 my $name = $section->name;
942 my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
943 print "Static $typename ${name}_list[$lines];\n";
944 }
945 }
946 $decl->output(\*STDOUT, "%s\n");
947 print "\n";
948 foreach $section (@sections) {
949 my $lines = $section->index + 1;
950 if ($lines) {
951 my $name = $section->name;
952 my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
953 printf "static %s %s_list[%u] = {\n", $typename, $name, $lines;
954 $section->output(\*STDOUT, "\t{ %s },\n");
955 print "};\n\n";
956 }
957 }
958
959 print <<"EOT";
960static int $init_name()
961{
962 dTHR;
af765ed9 963 dTARG;
964 djSP;
a798dbf2 965EOT
966 $init->output(\*STDOUT, "\t%s\n");
967 print "\treturn 0;\n}\n";
968 if ($verbose) {
969 warn compile_stats();
970 warn "NULLOP count: $nullop_count\n";
971 }
972}
973
974sub output_declarations {
975 print <<'EOT';
976#ifdef BROKEN_STATIC_REDECL
977#define Static extern
978#else
979#define Static static
980#endif /* BROKEN_STATIC_REDECL */
981
982#ifdef BROKEN_UNION_INIT
983/*
984 * Cribbed from cv.h with ANY (a union) replaced by void*.
985 * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
986 */
987typedef struct {
988 char * xpv_pv; /* pointer to malloced string */
989 STRLEN xpv_cur; /* length of xp_pv as a C string */
990 STRLEN xpv_len; /* allocated size */
991 IV xof_off; /* integer value */
992 double xnv_nv; /* numeric value, if any */
993 MAGIC* xmg_magic; /* magic for scalar array */
994 HV* xmg_stash; /* class package */
995
996 HV * xcv_stash;
997 OP * xcv_start;
998 OP * xcv_root;
20ce7b12 999 void (*xcv_xsub) (CV*);
a798dbf2 1000 void * xcv_xsubany;
1001 GV * xcv_gv;
1002 GV * xcv_filegv;
1003 long xcv_depth; /* >= 2 indicates recursive call */
1004 AV * xcv_padlist;
1005 CV * xcv_outside;
1006#ifdef USE_THREADS
1007 perl_mutex *xcv_mutexp;
1008 struct perl_thread *xcv_owner; /* current owner thread */
1009#endif /* USE_THREADS */
1010 U8 xcv_flags;
1011} XPVCV_or_similar;
1012#define ANYINIT(i) i
1013#else
1014#define XPVCV_or_similar XPVCV
1015#define ANYINIT(i) {i}
1016#endif /* BROKEN_UNION_INIT */
1017#define Nullany ANYINIT(0)
1018
1019#define UNUSED 0
1020#define sym_0 0
1021
1022EOT
1023 print "static GV *gv_list[$gv_index];\n" if $gv_index;
1024 print "\n";
1025}
1026
1027
1028sub output_boilerplate {
1029 print <<'EOT';
1030#include "EXTERN.h"
1031#include "perl.h"
a798dbf2 1032
1033/* Workaround for mapstart: the only op which needs a different ppaddr */
1034#undef pp_mapstart
1035#define pp_mapstart pp_grepstart
511dd457 1036#define XS_DynaLoader_boot_DynaLoader boot_DynaLoader
20ce7b12 1037EXTERN_C void boot_DynaLoader (CV* cv);
a798dbf2 1038
20ce7b12 1039static void xs_init (void);
a798dbf2 1040static PerlInterpreter *my_perl;
1041EOT
1042}
1043
1044sub output_main {
1045 print <<'EOT';
1046int
1047#ifndef CAN_PROTOTYPE
1048main(argc, argv, env)
1049int argc;
1050char **argv;
1051char **env;
1052#else /* def(CAN_PROTOTYPE) */
1053main(int argc, char **argv, char **env)
1054#endif /* def(CAN_PROTOTYPE) */
1055{
1056 int exitstatus;
1057 int i;
1058 char **fakeargv;
1059
1060 PERL_SYS_INIT(&argc,&argv);
1061
1062 perl_init_i18nl10n(1);
1063
81009501 1064 if (!PL_do_undump) {
a798dbf2 1065 my_perl = perl_alloc();
1066 if (!my_perl)
1067 exit(1);
1068 perl_construct( my_perl );
1069 }
1070
1071#ifdef CSH
81009501 1072 if (!PL_cshlen)
1073 PL_cshlen = strlen(PL_cshname);
a798dbf2 1074#endif
1075
1076#ifdef ALLOW_PERL_OPTIONS
1077#define EXTRA_OPTIONS 2
1078#else
1079#define EXTRA_OPTIONS 3
1080#endif /* ALLOW_PERL_OPTIONS */
1081 New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
1082 fakeargv[0] = argv[0];
1083 fakeargv[1] = "-e";
1084 fakeargv[2] = "";
1085#ifndef ALLOW_PERL_OPTIONS
1086 fakeargv[3] = "--";
1087#endif /* ALLOW_PERL_OPTIONS */
1088 for (i = 1; i < argc; i++)
1089 fakeargv[i + EXTRA_OPTIONS] = argv[i];
1090 fakeargv[argc + EXTRA_OPTIONS] = 0;
1091
1092 exitstatus = perl_parse(my_perl, xs_init, argc + EXTRA_OPTIONS,
1093 fakeargv, NULL);
1094 if (exitstatus)
1095 exit( exitstatus );
1096
1097 sv_setpv(GvSV(gv_fetchpv("0", TRUE, SVt_PV)), argv[0]);
81009501 1098 PL_main_cv = PL_compcv;
1099 PL_compcv = 0;
a798dbf2 1100
1101 exitstatus = perl_init();
1102 if (exitstatus)
1103 exit( exitstatus );
1104
1105 exitstatus = perl_run( my_perl );
1106
1107 perl_destruct( my_perl );
1108 perl_free( my_perl );
1109
1110 exit( exitstatus );
1111}
1112
511dd457 1113/* yanked from perl.c */
a798dbf2 1114static void
1115xs_init()
1116{
511dd457 1117 char *file = __FILE__;
af765ed9 1118 dTARG;
1119 djSP;
a798dbf2 1120EOT
af765ed9 1121 print "\n#ifdef USE_DYNAMIC_LOADING";
1122 print qq/\n\tnewXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);/;
1123 print "\n#endif\n" ;
1124 delete $xsub{'DynaLoader'};
1125 delete $xsub{'UNIVERSAL'};
1126 print("/* bootstrapping code*/\nSAVETMPS;\n");
1127 print("\ttarg=sv_newmortal();\n");
1128 foreach my $stashname (keys %xsub ){
1129 my $stashxsub=$stashname;
1130 $stashxsub =~ s/::/__/g;
1131 if ($xsub{$stashname} eq 'Dynamic') {
1132 print "#ifdef DYNALOADER_BOOTSTRAP\n";
1133 warn "bootstrapping $stashname added to xs_init\n";
1134 print qq/\n\t{\n\tchar *args[]={"$stashxsub", NULL};/;
1135 print qq/\n\t\tperl_call_argv("${stashxsub}::bootstrap",G_DISCARD,args);\n\t}/;
1136 print "\n#else\n";
1137 }
1138 print "\tPUSHMARK(sp);\n";
1139 print qq/\tXPUSHp("$stashname",strlen("$stashname")+1);\n/;
1140 print "\tboot_$stashxsub(NULL);\n";
1141 print "#endif\n" if ($xsub{$stashname} eq 'Dynamic');
1142 }
a798dbf2 1143
af765ed9 1144 print("\tFREETMPS;\n/* end bootstrapping code */\n");
1145 print "\n}";
1146}
a798dbf2 1147sub dump_symtable {
1148 # For debugging
1149 my ($sym, $val);
1150 warn "----Symbol table:\n";
1151 while (($sym, $val) = each %symtable) {
1152 warn "$sym => $val\n";
1153 }
1154 warn "---End of symbol table\n";
1155}
1156
1157sub save_object {
1158 my $sv;
1159 foreach $sv (@_) {
1160 svref_2object($sv)->save;
1161 }
338a6d08 1162}
1163
1164sub Dummy_BootStrap { }
a798dbf2 1165
66a2622e 1166sub B::GV::savecv
1167{
1168 my $gv = shift;
1169 my $package=$gv->STASH->NAME;
1170 my $name = $gv->NAME;
1171 my $cv = $gv->CV;
7cf11ee8 1172 my $sv = $gv->SV;
1173 my $av = $gv->AV;
1174 my $hv = $gv->HV;
1175 my $skip_cv = 0;
1176
66a2622e 1177 # We may be looking at this package just because it is a branch in the
1178 # symbol table which is on the path to a package which we need to save
7cf11ee8 1179 # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
66a2622e 1180 #
7cf11ee8 1181 return unless ($unused_sub_packages{$package});
66a2622e 1182 if ($$cv)
1183 {
1184 if ($name eq "bootstrap" && $cv->XSUB)
1185 {
7cf11ee8 1186 my $file = $cv->FILEGV->SV->PV;
66a2622e 1187 my $name = $gv->STASH->NAME.'::'.$name;
1188 no strict 'refs';
1189 *{$name} = \&Dummy_BootStrap;
af765ed9 1190 $xsub{$gv->STASH->NAME}='Dynamic';
66a2622e 1191 $cv = $gv->CV;
a798dbf2 1192 }
66a2622e 1193 warn sprintf("saving extra CV &%s::%s (0x%x) from GV 0x%x\n",
1194 $package, $name, $$cv, $$gv) if ($debug_cv);
7cf11ee8 1195 }
1196 else
66a2622e 1197 {
7cf11ee8 1198 return unless ($$av || $$sv || $$hv)
66a2622e 1199 }
7cf11ee8 1200 $gv->save($skip_cv);
66a2622e 1201}
5ed82aed 1202
66a2622e 1203sub mark_package
1204{
1205 my $package = shift;
1206 unless ($unused_sub_packages{$package})
1207 {
1208 no strict 'refs';
1209 $unused_sub_packages{$package} = 1;
1210 if (defined(@{$package.'::ISA'}))
1211 {
1212 foreach my $isa (@{$package.'::ISA'})
1213 {
1214 if ($isa eq 'DynaLoader')
1215 {
1216 unless (defined(&{$package.'::bootstrap'}))
1217 {
1218 warn "Forcing bootstrap of $package\n";
1219 eval { $package->bootstrap };
1220 }
1221 }
1222 else
1223 {
1224 unless ($unused_sub_packages{$isa})
1225 {
1226 warn "$isa saved (it is in $package\'s \@ISA)\n";
1227 mark_package($isa);
1228 }
1229 }
1230 }
1231 }
1232 }
1233 return 1;
1234}
1235
1236sub should_save
1237{
1238 no strict qw(vars refs);
1239 my $package = shift;
1240 $package =~ s/::$//;
1241 return $unused_sub_packages{$package} = 0 if ($package =~ /::::/); # skip ::::ISA::CACHE etc.
cf86991c 1242 # warn "Considering $package\n";#debug
66a2622e 1243 foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages))
1244 {
1245 # If this package is a prefix to something we are saving, traverse it
1246 # but do not mark it for saving if it is not already
1247 # e.g. to get to Getopt::Long we need to traverse Getopt but need
1248 # not save Getopt
1249 return 1 if ($u =~ /^$package\:\:/);
1250 }
1251 if (exists $unused_sub_packages{$package})
1252 {
cf86991c 1253 # warn "Cached $package is ".$unused_sub_packages{$package}."\n";
cfa4c8ee 1254 delete_unsaved_hashINC($package) unless $unused_sub_packages{$package} ;
1255 return $unused_sub_packages{$package};
66a2622e 1256 }
1257 # Omit the packages which we use (and which cause grief
1258 # because of fancy "goto &$AUTOLOAD" stuff).
1259 # XXX Surely there must be a nicer way to do this.
1260 if ($package eq "FileHandle" || $package eq "Config" ||
cf86991c 1261 $package eq "SelectSaver" || $package =~/^(B|IO)::/)
66a2622e 1262 {
cfa4c8ee 1263 delete_unsaved_hashINC($package);
66a2622e 1264 return $unused_sub_packages{$package} = 0;
1265 }
1266 # Now see if current package looks like an OO class this is probably too strong.
1267 foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE))
1268 {
1269 if ($package->can($m))
1270 {
1271 warn "$package has method $m: saving package\n";#debug
1272 return mark_package($package);
1273 }
1274 }
cfa4c8ee 1275 delete_unsaved_hashINC($package);
66a2622e 1276 return $unused_sub_packages{$package} = 0;
a798dbf2 1277}
cfa4c8ee 1278sub delete_unsaved_hashINC{
1279 my $packname=shift;
1280 $packname =~ s/\:\:/\//g;
1281 $packname .= '.pm';
59c10aa2 1282# warn "deleting $packname" if $INC{$packname} ;# debug
cfa4c8ee 1283 delete $INC{$packname};
1284}
66a2622e 1285sub walkpackages
1286{
1287 my ($symref, $recurse, $prefix) = @_;
1288 my $sym;
1289 my $ref;
1290 no strict 'vars';
1291 local(*glob);
1292 $prefix = '' unless defined $prefix;
1293 while (($sym, $ref) = each %$symref)
1294 {
1295 *glob = $ref;
1296 if ($sym =~ /::$/)
1297 {
1298 $sym = $prefix . $sym;
1299 if ($sym ne "main::" && &$recurse($sym))
1300 {
1301 walkpackages(\%glob, $recurse, $sym);
1302 }
1303 }
1304 }
1305}
338a6d08 1306
1307
66a2622e 1308sub save_unused_subs
1309{
1310 no strict qw(refs);
a9b6343a 1311 &descend_marked_unused;
66a2622e 1312 warn "Prescan\n";
1313 walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
1314 warn "Saving methods\n";
1315 walksymtable(\%{"main::"}, "savecv", \&should_save);
a798dbf2 1316}
1317
0cc1d052 1318sub save_context
1319{
1320 my $curpad_nam = (comppadlist->ARRAY)[0]->save;
1321 my $curpad_sym = (comppadlist->ARRAY)[1]->save;
1322 my $inc_hv = svref_2object(\%INC)->save;
1323 my $inc_av = svref_2object(\@INC)->save;
56eca212 1324 my $amagic_generate= amagic_generation;
0cc1d052 1325 $init->add( "PL_curpad = AvARRAY($curpad_sym);",
1326 "GvHV(PL_incgv) = $inc_hv;",
1327 "GvAV(PL_incgv) = $inc_av;",
1328 "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
56eca212 1329 "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
1330 "PL_amagic_generation= $amagic_generate;" );
0cc1d052 1331}
1332
a9b6343a 1333sub descend_marked_unused {
1334 foreach my $pack (keys %unused_sub_packages)
1335 {
1336 mark_package($pack);
1337 }
1338}
73544139 1339
a798dbf2 1340sub save_main {
66a2622e 1341 warn "Starting compile\n";
66a2622e 1342 warn "Walking tree\n";
73544139 1343 seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
a798dbf2 1344 walkoptree(main_root, "save");
1345 warn "done main optree, walking symtable for extras\n" if $debug_cv;
66a2622e 1346 save_unused_subs();
0cc1d052 1347 my $init_av = init_av->save;
81009501 1348 $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1349 sprintf("PL_main_start = s\\_%x;", ${main_start()}),
5ab5c7a4 1350 "PL_initav = (AV *) $init_av;");
0cc1d052 1351 save_context();
5ed82aed 1352 warn "Writing output\n";
a798dbf2 1353 output_boilerplate();
1354 print "\n";
1355 output_all("perl_init");
1356 print "\n";
1357 output_main();
1358}
1359
1360sub init_sections {
1361 my @sections = (init => \$init, decl => \$decl, sym => \$symsect,
1362 binop => \$binopsect, condop => \$condopsect,
66a2622e 1363 cop => \$copsect, gvop => \$gvopsect,
a798dbf2 1364 listop => \$listopsect, logop => \$logopsect,
1365 loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
1366 pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
1367 sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
1368 xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
1369 xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
1370 xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
1371 xrv => \$xrvsect, xpvbm => \$xpvbmsect,
af765ed9 1372 xpvio => \$xpviosect);
a798dbf2 1373 my ($name, $sectref);
1374 while (($name, $sectref) = splice(@sections, 0, 2)) {
66a2622e 1375 $$sectref = new B::C::Section $name, \%symtable, 0;
a798dbf2 1376 }
0cc1d052 1377}
1378
1379sub mark_unused
1380{
1381 my ($arg,$val) = @_;
1382 $unused_sub_packages{$arg} = $val;
a798dbf2 1383}
1384
1385sub compile {
1386 my @options = @_;
1387 my ($option, $opt, $arg);
1388 OPTION:
1389 while ($option = shift @options) {
1390 if ($option =~ /^-(.)(.*)/) {
1391 $opt = $1;
1392 $arg = $2;
1393 } else {
1394 unshift @options, $option;
1395 last OPTION;
1396 }
1397 if ($opt eq "-" && $arg eq "-") {
1398 shift @options;
1399 last OPTION;
1400 }
1401 if ($opt eq "w") {
1402 $warn_undefined_syms = 1;
1403 } elsif ($opt eq "D") {
1404 $arg ||= shift @options;
1405 foreach $arg (split(//, $arg)) {
1406 if ($arg eq "o") {
1407 B->debug(1);
1408 } elsif ($arg eq "c") {
1409 $debug_cops = 1;
1410 } elsif ($arg eq "A") {
1411 $debug_av = 1;
1412 } elsif ($arg eq "C") {
1413 $debug_cv = 1;
1414 } elsif ($arg eq "M") {
1415 $debug_mg = 1;
1416 } else {
1417 warn "ignoring unknown debug option: $arg\n";
1418 }
1419 }
1420 } elsif ($opt eq "o") {
1421 $arg ||= shift @options;
1422 open(STDOUT, ">$arg") or return "$arg: $!\n";
1423 } elsif ($opt eq "v") {
1424 $verbose = 1;
1425 } elsif ($opt eq "u") {
1426 $arg ||= shift @options;
0cc1d052 1427 mark_unused($arg,undef);
a798dbf2 1428 } elsif ($opt eq "f") {
1429 $arg ||= shift @options;
1430 if ($arg eq "cog") {
1431 $pv_copy_on_grow = 1;
1432 } elsif ($arg eq "no-cog") {
1433 $pv_copy_on_grow = 0;
1434 }
1435 } elsif ($opt eq "O") {
1436 $arg = 1 if $arg eq "";
1437 $pv_copy_on_grow = 0;
1438 if ($arg >= 1) {
1439 # Optimisations for -O1
1440 $pv_copy_on_grow = 1;
1441 }
1442 }
1443 }
1444 init_sections();
1445 if (@options) {
1446 return sub {
1447 my $objname;
1448 foreach $objname (@options) {
1449 eval "save_object(\\$objname)";
1450 }
1451 output_all();
1452 }
1453 } else {
1454 return sub { save_main() };
1455 }
1456}
1457
14581;
7f20e9dd 1459
1460__END__
1461
1462=head1 NAME
1463
1464B::C - Perl compiler's C backend
1465
1466=head1 SYNOPSIS
1467
1468 perl -MO=C[,OPTIONS] foo.pl
1469
1470=head1 DESCRIPTION
1471
1a52ab62 1472This compiler backend takes Perl source and generates C source code
1473corresponding to the internal structures that perl uses to run
1474your program. When the generated C source is compiled and run, it
1475cuts out the time which perl would have taken to load and parse
1476your program into its internal semi-compiled form. That means that
1477compiling with this backend will not help improve the runtime
1478execution speed of your program but may improve the start-up time.
1479Depending on the environment in which your program runs this may be
1480either a help or a hindrance.
1481
1482=head1 OPTIONS
1483
1484If there are any non-option arguments, they are taken to be
1485names of objects to be saved (probably doesn't work properly yet).
1486Without extra arguments, it saves the main program.
1487
1488=over 4
1489
1490=item B<-ofilename>
1491
1492Output to filename instead of STDOUT
1493
1494=item B<-v>
1495
1496Verbose compilation (currently gives a few compilation statistics).
1497
1498=item B<-->
1499
1500Force end of options
1501
1502=item B<-uPackname>
1503
1504Force apparently unused subs from package Packname to be compiled.
1505This allows programs to use eval "foo()" even when sub foo is never
1506seen to be used at compile time. The down side is that any subs which
1507really are never used also have code generated. This option is
1508necessary, for example, if you have a signal handler foo which you
1509initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
1510to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
1511options. The compiler tries to figure out which packages may possibly
1512have subs in which need compiling but the current version doesn't do
1513it very well. In particular, it is confused by nested packages (i.e.
1514of the form C<A::B>) where package C<A> does not contain any subs.
1515
1516=item B<-D>
1517
1518Debug options (concatenated or separate flags like C<perl -D>).
1519
1520=item B<-Do>
1521
1522OPs, prints each OP as it's processed
1523
1524=item B<-Dc>
1525
1526COPs, prints COPs as processed (incl. file & line num)
1527
1528=item B<-DA>
1529
1530prints AV information on saving
1531
1532=item B<-DC>
1533
1534prints CV information on saving
1535
1536=item B<-DM>
1537
1538prints MAGIC information on saving
1539
1540=item B<-f>
1541
1542Force optimisations on or off one at a time.
1543
1544=item B<-fcog>
1545
1546Copy-on-grow: PVs declared and initialised statically.
1547
1548=item B<-fno-cog>
1549
1550No copy-on-grow.
1551
1552=item B<-On>
1553
1554Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. Currently,
1555B<-O1> and higher set B<-fcog>.
1556
1557=head1 EXAMPLES
1558
1559 perl -MO=C,-ofoo.c foo.pl
1560 perl cc_harness -o foo foo.c
1561
1562Note that C<cc_harness> lives in the C<B> subdirectory of your perl
1563library directory. The utility called C<perlcc> may also be used to
1564help make use of this compiler.
1565
1566 perl -MO=C,-v,-DcA bar.pl > /dev/null
1567
1568=head1 BUGS
1569
1570Plenty. Current status: experimental.
7f20e9dd 1571
1572=head1 AUTHOR
1573
1574Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
1575
1576=cut