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