This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
927931725b2ed4512ed6c3b9709bfb5099ff6b1b
[perl5.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
9 package B::C;
10
11 our $VERSION = '1.04';
12
13 package B::C::Section;
14
15 use B ();
16 use base B::Section;
17
18 sub new
19 {
20  my $class = shift;
21  my $o = $class->SUPER::new(@_);
22  push @$o, { values => [] };
23  return $o;
24 }
25
26 sub add
27 {
28  my $section = shift;
29  push(@{$section->[-1]{values}},@_);
30 }
31
32 sub index
33 {
34  my $section = shift;
35  return scalar(@{$section->[-1]{values}})-1;
36 }
37
38 sub output
39 {
40  my ($section, $fh, $format) = @_;
41  my $sym = $section->symtable || {};
42  my $default = $section->default;
43  my $i;
44  foreach (@{$section->[-1]{values}})
45   {
46    s{(s\\_[0-9a-f]+)}{ exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
47    printf $fh $format, $_, $i;
48    ++$i;
49   }
50 }
51
52 package B::C::InitSection;
53
54 # avoid use vars
55 @B::C::InitSection::ISA = qw(B::C::Section);
56
57 sub new {
58     my $class = shift;
59     my $max_lines = 10000; #pop;
60     my $section = $class->SUPER::new( @_ );
61
62     $section->[-1]{evals} = [];
63     $section->[-1]{chunks} = [];
64     $section->[-1]{nosplit} = 0;
65     $section->[-1]{current} = [];
66     $section->[-1]{count} = 0;
67     $section->[-1]{max_lines} = $max_lines;
68
69     return $section;
70 }
71
72 sub split {
73     my $section = shift;
74     $section->[-1]{nosplit}--
75       if $section->[-1]{nosplit} > 0;
76 }
77
78 sub no_split {
79     shift->[-1]{nosplit}++;
80 }
81
82 sub inc_count {
83     my $section = shift;
84
85     $section->[-1]{count} += $_[0];
86     # this is cheating
87     $section->add();
88 }
89
90 sub add {
91     my $section = shift->[-1];
92     my $current = $section->{current};
93     my $nosplit = $section->{nosplit};
94
95     push @$current, @_;
96     $section->{count} += scalar(@_);
97     if( !$nosplit && $section->{count} >= $section->{max_lines} ) {
98         push @{$section->{chunks}}, $current;
99         $section->{current} = [];
100         $section->{count} = 0;
101     }
102 }
103
104 sub add_eval {
105     my $section = shift;
106     my @strings = @_;
107
108     foreach my $i ( @strings ) {
109         $i =~ s/\"/\\\"/g;
110     }
111     push @{$section->[-1]{evals}}, @strings;
112 }
113
114 sub output {
115     my( $section, $fh, $format, $init_name ) = @_;
116     my $sym = $section->symtable || {};
117     my $default = $section->default;
118     push @{$section->[-1]{chunks}}, $section->[-1]{current};
119
120     my $name = "aaaa";
121     foreach my $i ( @{$section->[-1]{chunks}} ) {
122         print $fh <<"EOT";
123 static int perl_init_${name}()
124 {
125         dTARG;
126         dSP;
127 EOT
128         foreach my $j ( @$i ) {
129             $j =~ s{(s\\_[0-9a-f]+)}
130                    { exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
131             print $fh "\t$j\n";
132         }
133         print $fh "\treturn 0;\n}\n";
134
135         $section->SUPER::add( "perl_init_${name}();" );
136         ++$name;
137     }
138     foreach my $i ( @{$section->[-1]{evals}} ) {
139         $section->SUPER::add( sprintf q{eval_pv("%s",1);}, $i );
140     }
141
142     print $fh <<"EOT";
143 static int ${init_name}()
144 {
145         dTARG;
146         dSP;
147 EOT
148     $section->SUPER::output( $fh, $format );
149     print $fh "\treturn 0;\n}\n";
150 }
151
152
153 package B::C;
154 use Exporter ();
155 our %REGEXP;
156
157 { # block necessary for caller to work
158     my $caller = caller;
159     if( $caller eq 'O' ) {
160         require XSLoader;
161         XSLoader::load( 'B::C' );
162     }
163 }
164
165 @ISA = qw(Exporter);
166 @EXPORT_OK = qw(output_all output_boilerplate output_main mark_unused
167                 init_sections set_callback save_unused_subs objsym save_context);
168
169 use B qw(minus_c sv_undef walkoptree walksymtable main_root main_start peekop
170          class cstring cchar svref_2object compile_stats comppadlist hash
171          threadsv_names main_cv init_av end_av regex_padav opnumber amagic_generation
172          AVf_REAL HEf_SVKEY SVf_POK SVf_ROK CVf_CONST);
173 use B::Asmdata qw(@specialsv_name);
174
175 use FileHandle;
176 use Carp;
177 use strict;
178 use Config;
179
180 my $hv_index = 0;
181 my $gv_index = 0;
182 my $re_index = 0;
183 my $pv_index = 0;
184 my $cv_index = 0;
185 my $anonsub_index = 0;
186 my $initsub_index = 0;
187
188 my %symtable;
189 my %xsub;
190 my $warn_undefined_syms;
191 my $verbose;
192 my %unused_sub_packages;
193 my $use_xsloader;
194 my $nullop_count;
195 my $pv_copy_on_grow = 0;
196 my $optimize_ppaddr = 0;
197 my $optimize_warn_sv = 0;
198 my $use_perl_script_name = 0;
199 my $save_data_fh = 0;
200 my $save_sig = 0;
201 my ($debug_cops, $debug_av, $debug_cv, $debug_mg);
202 my $max_string_len;
203
204 my $ithreads = $Config{useithreads} eq 'define';
205
206 my @threadsv_names;
207 BEGIN {
208     @threadsv_names = threadsv_names();
209 }
210
211 # Code sections
212 my ($init, $decl, $symsect, $binopsect, $condopsect, $copsect, 
213     $padopsect, $listopsect, $logopsect, $loopsect, $opsect, $pmopsect,
214     $pvopsect, $svopsect, $unopsect, $svsect, $xpvsect, $xpvavsect,
215     $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect, $xpvmgsect, $xpvlvsect,
216     $xrvsect, $xpvbmsect, $xpviosect );
217 my @op_sections = \( $binopsect, $condopsect, $copsect, $padopsect, $listopsect,
218                      $logopsect, $loopsect, $opsect, $pmopsect, $pvopsect, $svopsect,
219                      $unopsect );
220
221 sub walk_and_save_optree;
222 my $saveoptree_callback = \&walk_and_save_optree;
223 sub set_callback { $saveoptree_callback = shift }
224 sub saveoptree { &$saveoptree_callback(@_) }
225
226 sub walk_and_save_optree {
227     my ($name, $root, $start) = @_;
228     walkoptree($root, "save");
229     return objsym($start);
230 }
231
232 # Look this up here so we can do just a number compare
233 # rather than looking up the name of every BASEOP in B::OP
234 my $OP_THREADSV = opnumber('threadsv');
235
236 sub savesym {
237     my ($obj, $value) = @_;
238     my $sym = sprintf("s\\_%x", $$obj);
239     $symtable{$sym} = $value;
240 }
241
242 sub objsym {
243     my $obj = shift;
244     return $symtable{sprintf("s\\_%x", $$obj)};
245 }
246
247 sub getsym {
248     my $sym = shift;
249     my $value;
250
251     return 0 if $sym eq "sym_0";        # special case
252     $value = $symtable{$sym};
253     if (defined($value)) {
254         return $value;
255     } else {
256         warn "warning: undefined symbol $sym\n" if $warn_undefined_syms;
257         return "UNUSED";
258     }
259 }
260
261 sub savere {
262     my $re = shift;
263     my $sym = sprintf("re%d", $re_index++);
264     $decl->add(sprintf("static char *$sym = %s;", cstring($re)));
265
266     return ($sym,length(pack "a*",$re));
267 }
268
269 sub savepv {
270     my $pv = pack "a*", shift;
271     my $pvsym = 0;
272     my $pvmax = 0;
273     if ($pv_copy_on_grow) {
274         $pvsym = sprintf("pv%d", $pv_index++);
275
276         if( defined $max_string_len && length($pv) > $max_string_len ) {
277             my $chars = join ', ', map { cchar $_ } split //, $pv;
278             $decl->add(sprintf("static char %s[] = { %s };", $pvsym, $chars));
279         }
280         else {
281              my $cstring = cstring($pv);
282             if ($cstring ne "0") { # sic
283                 $decl->add(sprintf("static char %s[] = %s;",
284                                    $pvsym, $cstring));
285             }
286         }
287     } else {
288         $pvmax = length(pack "a*",$pv) + 1;
289     }
290     return ($pvsym, $pvmax);
291 }
292
293 sub save_rv {
294     my $sv = shift;
295 #    confess "Can't save RV: not ROK" unless $sv->FLAGS & SVf_ROK;
296     my $rv = $sv->RV->save;
297
298     $rv =~ s/^\(([AGHS]V|IO)\s*\*\)\s*(\&sv_list.*)$/$2/;
299
300     return $rv;
301 }
302
303 # savesym, pvmax, len, pv
304 sub save_pv_or_rv {
305     my $sv = shift;
306
307     my $rok = $sv->FLAGS & SVf_ROK;
308     my $pok = $sv->FLAGS & SVf_POK;
309     my( $len, $pvmax, $savesym, $pv ) = ( 0, 0 );
310     if( $rok ) {
311        $savesym = '(char*)' . save_rv( $sv );
312     }
313     else {
314        $pv = $pok ? (pack "a*", $sv->PV) : undef;
315        $len = $pok ? length($pv) : 0;
316        ($savesym, $pvmax) = $pok ? savepv($pv) : ( 'NULL', 0 );
317     }
318
319     return ( $savesym, $pvmax, $len, $pv );
320 }
321
322 # see also init_op_ppaddr below; initializes the ppaddt to the
323 # OpTYPE; init_op_ppaddr iterates over the ops and sets
324 # op_ppaddr to PL_ppaddr[op_ppaddr]; this avoids an explicit assignmente
325 # in perl_init ( ~10 bytes/op with GCC/i386 )
326 sub B::OP::fake_ppaddr {
327     return $optimize_ppaddr ?
328       sprintf("INT2PTR(void*,OP_%s)", uc( $_[0]->name ) ) :
329       'NULL';
330 }
331
332 # This pair is needed becase B::FAKEOP::save doesn't scalar dereference
333 # $op->next and $op->sibling
334
335 {
336   # For 5.9 the hard coded text is the values for op_opt and op_static in each
337   # op.  The value of op_opt is irrelevant, and the value of op_static needs to
338   # be 1 to tell op_free that this is a statically defined op and that is
339   # shouldn't be freed.
340
341   # For 5.8:
342   # Current workaround/fix for op_free() trying to free statically
343   # defined OPs is to set op_seq = -1 and check for that in op_free().
344   # Instead of hardwiring -1 in place of $op->seq, we use $op_seq
345   # so that it can be changed back easily if necessary. In fact, to
346   # stop compilers from moaning about a U16 being initialised with an
347   # uncast -1 (the printf format is %d so we can't tweak it), we have
348   # to "know" that op_seq is a U16 and use 65535. Ugh.
349
350   my $static = $] > 5.009 ? '0, 1, 0' : sprintf "%u", 65535;
351   sub B::OP::_save_common_middle {
352     my $op = shift;
353     sprintf ("%s, %u, %u, $static, 0x%x, 0x%x",
354              $op->fake_ppaddr, $op->targ, $op->type, $op->flags, $op->private);
355   }
356 }
357
358 sub B::OP::_save_common {
359  my $op = shift;
360  return sprintf("s\\_%x, s\\_%x, %s",
361                 ${$op->next}, ${$op->sibling}, $op->_save_common_middle);
362 }
363
364 sub B::OP::save {
365     my ($op, $level) = @_;
366     my $sym = objsym($op);
367     return $sym if defined $sym;
368     my $type = $op->type;
369     $nullop_count++ unless $type;
370     if ($type == $OP_THREADSV) {
371         # saves looking up ppaddr but it's a bit naughty to hard code this
372         $init->add(sprintf("(void)find_threadsv(%s);",
373                            cstring($threadsv_names[$op->targ])));
374     }
375     $opsect->add($op->_save_common);
376     my $ix = $opsect->index;
377     $init->add(sprintf("op_list[$ix].op_ppaddr = %s;", $op->ppaddr))
378         unless $optimize_ppaddr;
379     savesym($op, "&op_list[$ix]");
380 }
381
382 sub B::FAKEOP::new {
383     my ($class, %objdata) = @_;
384     bless \%objdata, $class;
385 }
386
387 sub B::FAKEOP::save {
388     my ($op, $level) = @_;
389     $opsect->add(sprintf("%s, %s, %s",
390                          $op->next, $op->sibling, $op->_save_common_middle));
391     my $ix = $opsect->index;
392     $init->add(sprintf("op_list[$ix].op_ppaddr = %s;", $op->ppaddr))
393         unless $optimize_ppaddr;
394     return "&op_list[$ix]";
395 }
396
397 sub B::FAKEOP::next { $_[0]->{"next"} || 0 }
398 sub B::FAKEOP::type { $_[0]->{type} || 0}
399 sub B::FAKEOP::sibling { $_[0]->{sibling} || 0 }
400 sub B::FAKEOP::ppaddr { $_[0]->{ppaddr} || 0 }
401 sub B::FAKEOP::targ { $_[0]->{targ} || 0 }
402 sub B::FAKEOP::flags { $_[0]->{flags} || 0 }
403 sub B::FAKEOP::private { $_[0]->{private} || 0 }
404
405 sub B::UNOP::save {
406     my ($op, $level) = @_;
407     my $sym = objsym($op);
408     return $sym if defined $sym;
409     $unopsect->add(sprintf("%s, s\\_%x", $op->_save_common, ${$op->first}));
410     my $ix = $unopsect->index;
411     $init->add(sprintf("unop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
412         unless $optimize_ppaddr;
413     savesym($op, "(OP*)&unop_list[$ix]");
414 }
415
416 sub B::BINOP::save {
417     my ($op, $level) = @_;
418     my $sym = objsym($op);
419     return $sym if defined $sym;
420     $binopsect->add(sprintf("%s, s\\_%x, s\\_%x",
421                             $op->_save_common, ${$op->first}, ${$op->last}));
422     my $ix = $binopsect->index;
423     $init->add(sprintf("binop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
424         unless $optimize_ppaddr;
425     savesym($op, "(OP*)&binop_list[$ix]");
426 }
427
428 sub B::LISTOP::save {
429     my ($op, $level) = @_;
430     my $sym = objsym($op);
431     return $sym if defined $sym;
432     $listopsect->add(sprintf("%s, s\\_%x, s\\_%x",
433                              $op->_save_common, ${$op->first}, ${$op->last}));
434     my $ix = $listopsect->index;
435     $init->add(sprintf("listop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
436         unless $optimize_ppaddr;
437     savesym($op, "(OP*)&listop_list[$ix]");
438 }
439
440 sub B::LOGOP::save {
441     my ($op, $level) = @_;
442     my $sym = objsym($op);
443     return $sym if defined $sym;
444     $logopsect->add(sprintf("%s, s\\_%x, s\\_%x",
445                             $op->_save_common, ${$op->first}, ${$op->other}));
446     my $ix = $logopsect->index;
447     $init->add(sprintf("logop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
448         unless $optimize_ppaddr;
449     savesym($op, "(OP*)&logop_list[$ix]");
450 }
451
452 sub B::LOOP::save {
453     my ($op, $level) = @_;
454     my $sym = objsym($op);
455     return $sym if defined $sym;
456     #warn sprintf("LOOP: redoop %s, nextop %s, lastop %s\n",
457     #            peekop($op->redoop), peekop($op->nextop),
458     #            peekop($op->lastop)); # debug
459     $loopsect->add(sprintf("%s, s\\_%x, s\\_%x, s\\_%x, s\\_%x, s\\_%x",
460                            $op->_save_common, ${$op->first}, ${$op->last},
461                            ${$op->redoop}, ${$op->nextop},
462                            ${$op->lastop}));
463     my $ix = $loopsect->index;
464     $init->add(sprintf("loop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
465         unless $optimize_ppaddr;
466     savesym($op, "(OP*)&loop_list[$ix]");
467 }
468
469 sub B::PVOP::save {
470     my ($op, $level) = @_;
471     my $sym = objsym($op);
472     return $sym if defined $sym;
473     $pvopsect->add(sprintf("%s, %s", $op->_save_common, cstring($op->pv)));
474     my $ix = $pvopsect->index;
475     $init->add(sprintf("pvop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
476         unless $optimize_ppaddr;
477     savesym($op, "(OP*)&pvop_list[$ix]");
478 }
479
480 sub B::SVOP::save {
481     my ($op, $level) = @_;
482     my $sym = objsym($op);
483     return $sym if defined $sym;
484     my $sv = $op->sv;
485     my $svsym = '(SV*)' . $sv->save;
486     my $is_const_addr = $svsym =~ m/Null|\&/;
487     $svopsect->add(sprintf("%s, %s", $op->_save_common,
488                            ( $is_const_addr ? $svsym : 'Nullsv' )));
489     my $ix = $svopsect->index;
490     $init->add(sprintf("svop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
491         unless $optimize_ppaddr;
492     $init->add("svop_list[$ix].op_sv = $svsym;")
493         unless $is_const_addr;
494     savesym($op, "(OP*)&svop_list[$ix]");
495 }
496
497 sub B::PADOP::save {
498     my ($op, $level) = @_;
499     my $sym = objsym($op);
500     return $sym if defined $sym;
501     $padopsect->add(sprintf("%s, %d",
502                             $op->_save_common, $op->padix));
503     my $ix = $padopsect->index;
504     $init->add(sprintf("padop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
505         unless $optimize_ppaddr;
506 #    $init->add(sprintf("padop_list[$ix].op_padix = %ld;", $op->padix));
507     savesym($op, "(OP*)&padop_list[$ix]");
508 }
509
510 sub B::COP::save {
511     my ($op, $level) = @_;
512     my $sym = objsym($op);
513     return $sym if defined $sym;
514     warn sprintf("COP: line %d file %s\n", $op->line, $op->file)
515         if $debug_cops;
516     # shameless cut'n'paste from B::Deparse
517     my $warn_sv;
518     my $warnings = $op->warnings;
519     my $is_special = $warnings->isa("B::SPECIAL");
520     if ($is_special && $$warnings == 4) {
521         # use warnings 'all';
522         $warn_sv = $optimize_warn_sv ?
523             'INT2PTR(SV*,1)' :
524             'pWARN_ALL';
525     }
526     elsif ($is_special && $$warnings == 5) {
527         # no warnings 'all';
528         $warn_sv = $optimize_warn_sv ?
529             'INT2PTR(SV*,2)' :
530             'pWARN_NONE';
531     }
532     elsif ($is_special) {
533         # use warnings;
534         $warn_sv = $optimize_warn_sv ?
535             'INT2PTR(SV*,3)' :
536             'pWARN_STD';
537     }
538     else {
539         # something else
540         $warn_sv = $warnings->save;
541     }
542
543     $copsect->add(sprintf("%s, %s, NULL, NULL, %u, %d, %u, %s",
544                           $op->_save_common, cstring($op->label), $op->cop_seq,
545                           $op->arybase, $op->line,
546                           ( $optimize_warn_sv ? $warn_sv : 'NULL' )));
547     my $ix = $copsect->index;
548     $init->add(sprintf("cop_list[$ix].op_ppaddr = %s;", $op->ppaddr))
549         unless $optimize_ppaddr;
550     $init->add(sprintf("cop_list[$ix].cop_warnings = %s;", $warn_sv ))
551         unless $optimize_warn_sv;
552     $init->add(sprintf("CopFILE_set(&cop_list[$ix], %s);", cstring($op->file)),
553                sprintf("CopSTASHPV_set(&cop_list[$ix], %s);", cstring($op->stashpv)));
554
555     savesym($op, "(OP*)&cop_list[$ix]");
556 }
557
558 sub B::PMOP::save {
559     my ($op, $level) = @_;
560     my $sym = objsym($op);
561     return $sym if defined $sym;
562     my $replroot = $op->pmreplroot;
563     my $replstart = $op->pmreplstart;
564     my $replrootfield;
565     my $replstartfield = sprintf("s\\_%x", $$replstart);
566     my $gvsym;
567     my $ppaddr = $op->ppaddr;
568     # under ithreads, OP_PUSHRE.op_replroot is an integer
569     $replrootfield = sprintf("s\\_%x", $$replroot) if ref $replroot;
570     if($ithreads && $op->name eq "pushre") {
571         $replrootfield = "INT2PTR(OP*,${replroot})";
572     } elsif ($$replroot) {
573         # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
574         # argument to a split) stores a GV in op_pmreplroot instead
575         # of a substitution syntax tree. We don't want to walk that...
576         if ($op->name eq "pushre") {
577             $gvsym = $replroot->save;
578 #           warn "PMOP::save saving a pp_pushre with GV $gvsym\n"; # debug
579             $replrootfield = 0;
580         } else {
581             $replstartfield = saveoptree("*ignore*", $replroot, $replstart);
582         }
583     }
584     # pmnext handling is broken in perl itself, I think. Bad op_pmnext
585     # fields aren't noticed in perl's runtime (unless you try reset) but we
586     # segfault when trying to dereference it to find op->op_pmnext->op_type
587     $pmopsect->add(sprintf("%s, s\\_%x, s\\_%x, %s, %s, 0, %u, 0x%x, 0x%x, 0x%x",
588                            $op->_save_common, ${$op->first}, ${$op->last},
589                            $replrootfield, $replstartfield,
590                            ( $ithreads ? $op->pmoffset : 0 ),
591                            $op->pmflags, $op->pmpermflags, $op->pmdynflags ));
592     my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
593     $init->add(sprintf("$pm.op_ppaddr = %s;", $ppaddr))
594         unless $optimize_ppaddr;
595     my $re = $op->precomp;
596     if (defined($re)) {
597         my( $resym, $relen ) = savere( $re );
598         $init->add(sprintf("PM_SETRE(&$pm,pregcomp($resym, $resym + %u, &$pm));",
599                            $relen));
600     }
601     if ($gvsym) {
602         $init->add("$pm.op_pmreplroot = (OP*)$gvsym;");
603     }
604     savesym($op, "(OP*)&$pm");
605 }
606
607 sub B::SPECIAL::save {
608     my ($sv) = @_;
609     # special case: $$sv is not the address but an index into specialsv_list
610 #   warn "SPECIAL::save specialsv $$sv\n"; # debug
611     my $sym = $specialsv_name[$$sv];
612     if (!defined($sym)) {
613         confess "unknown specialsv index $$sv passed to B::SPECIAL::save";
614     }
615     return $sym;
616 }
617
618 sub B::OBJECT::save {}
619
620 sub B::NULL::save {
621     my ($sv) = @_;
622     my $sym = objsym($sv);
623     return $sym if defined $sym;
624 #   warn "Saving SVt_NULL SV\n"; # debug
625     # debug
626     if ($$sv == 0) {
627         warn "NULL::save for sv = 0 called from @{[(caller(1))[3]]}\n";
628         return savesym($sv, "(void*)Nullsv /* XXX */");
629     }
630     $svsect->add(sprintf("0, %u, 0x%x", $sv->REFCNT , $sv->FLAGS));
631     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
632 }
633
634 sub B::IV::save {
635     my ($sv) = @_;
636     my $sym = objsym($sv);
637     return $sym if defined $sym;
638     $xpvivsect->add(sprintf("0, 0, 0, %d", $sv->IVX));
639     $svsect->add(sprintf("&xpviv_list[%d], %lu, 0x%x",
640                          $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
641     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
642 }
643
644 sub B::NV::save {
645     my ($sv) = @_;
646     my $sym = objsym($sv);
647     return $sym if defined $sym;
648     my $val= $sv->NVX;
649     $val .= '.00' if $val =~ /^-?\d+$/;
650     $xpvnvsect->add(sprintf("0, 0, 0, %d, %s", $sv->IVX, $val));
651     $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
652                          $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
653     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
654 }
655
656 sub savepvn {
657     my ($dest,$pv) = @_;
658     my @res;
659     # work with byte offsets/lengths
660     my $pv = pack "a*", $pv;
661     if (defined $max_string_len && length($pv) > $max_string_len) {
662         push @res, sprintf("New(0,%s,%u,char);", $dest, length($pv)+1);
663         my $offset = 0;
664         while (length $pv) {
665             my $str = substr $pv, 0, $max_string_len, '';
666             push @res, sprintf("Copy(%s,$dest+$offset,%u,char);",
667                                cstring($str), length($str));
668             $offset += length $str;
669         }
670         push @res, sprintf("%s[%u] = '\\0';", $dest, $offset);
671     }
672     else {
673         push @res, sprintf("%s = savepvn(%s, %u);", $dest,
674                            cstring($pv), length($pv));
675     }
676     return @res;
677 }
678
679 sub B::PVLV::save {
680     my ($sv) = @_;
681     my $sym = objsym($sv);
682     return $sym if defined $sym;
683     my $pv = $sv->PV;
684     my $len = length($pv);
685     my ($pvsym, $pvmax) = savepv($pv);
686     my ($lvtarg, $lvtarg_sym);
687     $xpvlvsect->add(sprintf("%s, %u, %u, %d, %g, 0, 0, %u, %u, 0, %s",
688                             $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX, 
689                             $sv->TARGOFF, $sv->TARGLEN, cchar($sv->TYPE)));
690     $svsect->add(sprintf("&xpvlv_list[%d], %lu, 0x%x",
691                          $xpvlvsect->index, $sv->REFCNT , $sv->FLAGS));
692     if (!$pv_copy_on_grow) {
693         $init->add(savepvn(sprintf("xpvlv_list[%d].xpv_pv",
694                                    $xpvlvsect->index), $pv));
695     }
696     $sv->save_magic;
697     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
698 }
699
700 sub B::PVIV::save {
701     my ($sv) = @_;
702     my $sym = objsym($sv);
703     return $sym if defined $sym;
704     my( $savesym, $pvmax, $len, $pv ) = save_pv_or_rv( $sv );
705     $xpvivsect->add(sprintf("%s, %u, %u, %d", $savesym, $len, $pvmax, $sv->IVX));
706     $svsect->add(sprintf("&xpviv_list[%d], %u, 0x%x",
707                          $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
708     if (defined($pv) && !$pv_copy_on_grow) {
709         $init->add(savepvn(sprintf("xpviv_list[%d].xpv_pv",
710                                    $xpvivsect->index), $pv));
711     }
712     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
713 }
714
715 sub B::PVNV::save {
716     my ($sv) = @_;
717     my $sym = objsym($sv);
718     return $sym if defined $sym;
719     my( $savesym, $pvmax, $len, $pv ) = save_pv_or_rv( $sv );
720     my $val= $sv->NVX;
721     $val .= '.00' if $val =~ /^-?\d+$/;
722     $xpvnvsect->add(sprintf("%s, %u, %u, %d, %s",
723                             $savesym, $len, $pvmax, $sv->IVX, $val));
724     $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
725                          $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
726     if (defined($pv) && !$pv_copy_on_grow) {
727         $init->add(savepvn(sprintf("xpvnv_list[%d].xpv_pv",
728                                    $xpvnvsect->index), $pv));
729     }
730     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
731 }
732
733 sub B::BM::save {
734     my ($sv) = @_;
735     my $sym = objsym($sv);
736     return $sym if defined $sym;
737     my $pv = pack "a*", ($sv->PV . "\0" . $sv->TABLE);
738     my $len = length($pv);
739     $xpvbmsect->add(sprintf("0, %u, %u, %d, %s, 0, 0, %d, %u, 0x%x",
740                             $len, $len + 258, $sv->IVX, $sv->NVX,
741                             $sv->USEFUL, $sv->PREVIOUS, $sv->RARE));
742     $svsect->add(sprintf("&xpvbm_list[%d], %lu, 0x%x",
743                          $xpvbmsect->index, $sv->REFCNT , $sv->FLAGS));
744     $sv->save_magic;
745     $init->add(savepvn(sprintf("xpvbm_list[%d].xpv_pv",
746                                $xpvbmsect->index), $pv),
747                sprintf("xpvbm_list[%d].xpv_cur = %u;",
748                        $xpvbmsect->index, $len - 257));
749     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
750 }
751
752 sub B::PV::save {
753     my ($sv) = @_;
754     my $sym = objsym($sv);
755     return $sym if defined $sym;
756     my( $savesym, $pvmax, $len, $pv ) = save_pv_or_rv( $sv );
757     $xpvsect->add(sprintf("%s, %u, %u", $savesym, $len, $pvmax));
758     $svsect->add(sprintf("&xpv_list[%d], %lu, 0x%x",
759                          $xpvsect->index, $sv->REFCNT , $sv->FLAGS));
760     if (defined($pv) && !$pv_copy_on_grow) {
761         $init->add(savepvn(sprintf("xpv_list[%d].xpv_pv",
762                                    $xpvsect->index), $pv));
763     }
764     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
765 }
766
767 sub B::PVMG::save {
768     my ($sv) = @_;
769     my $sym = objsym($sv);
770     return $sym if defined $sym;
771     my( $savesym, $pvmax, $len, $pv ) = save_pv_or_rv( $sv );
772
773     $xpvmgsect->add(sprintf("%s, %u, %u, %d, %s, 0, 0",
774                             $savesym, $len, $pvmax,
775                             $sv->IVX, $sv->NVX));
776     $svsect->add(sprintf("&xpvmg_list[%d], %lu, 0x%x",
777                          $xpvmgsect->index, $sv->REFCNT , $sv->FLAGS));
778     if (defined($pv) && !$pv_copy_on_grow) {
779         $init->add(savepvn(sprintf("xpvmg_list[%d].xpv_pv",
780                                    $xpvmgsect->index), $pv));
781     }
782     $sym = savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
783     $sv->save_magic;
784     return $sym;
785 }
786
787 sub B::PVMG::save_magic {
788     my ($sv) = @_;
789     #warn sprintf("saving magic for %s (0x%x)\n", class($sv), $$sv); # debug
790     my $stash = $sv->SvSTASH;
791     $stash->save;
792     if ($$stash) {
793         warn sprintf("xmg_stash = %s (0x%x)\n", $stash->NAME, $$stash)
794             if $debug_mg;
795         # XXX Hope stash is already going to be saved.
796         $init->add(sprintf("SvSTASH(s\\_%x) = s\\_%x;", $$sv, $$stash));
797     }
798     my @mgchain = $sv->MAGIC;
799     my ($mg, $type, $obj, $ptr,$len,$ptrsv);
800     foreach $mg (@mgchain) {
801         $type = $mg->TYPE;
802         $ptr = $mg->PTR;
803         $len=$mg->LENGTH;
804         if ($debug_mg) {
805             warn sprintf("magic %s (0x%x), obj %s (0x%x), type %s, ptr %s\n",
806                          class($sv), $$sv, class($obj), $$obj,
807                          cchar($type), cstring($ptr));
808         }
809
810         unless( $type eq 'r' ) {
811           $obj = $mg->OBJ;
812           $obj->save;
813         }
814
815         if ($len == HEf_SVKEY){
816                 #The pointer is an SV*
817                 $ptrsv=svref_2object($ptr)->save;
818                 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s,(char *) %s, %d);",
819                            $$sv, $$obj, cchar($type),$ptrsv,$len));
820         }elsif( $type eq 'r' ){
821             my $rx = $mg->REGEX;
822             my $pmop = $REGEXP{$rx};
823
824             confess "PMOP not found for REGEXP $rx" unless $pmop;
825
826             my( $resym, $relen ) = savere( $mg->precomp );
827             my $pmsym = $pmop->save;
828             $init->add( split /\n/, sprintf <<CODE, $$sv, cchar($type), cstring($ptr) );
829 {
830     REGEXP* rx = pregcomp($resym, $resym + $relen, (PMOP*)$pmsym);
831     sv_magic((SV*)s\\_%x, (SV*)rx, %s, %s, %d);
832 }
833 CODE
834         }else{
835                 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
836                            $$sv, $$obj, cchar($type),cstring($ptr),$len));
837         }
838     }
839 }
840
841 sub B::RV::save {
842     my ($sv) = @_;
843     my $sym = objsym($sv);
844     return $sym if defined $sym;
845     my $rv = save_rv( $sv );
846     # GVs need to be handled at runtime
847     if( ref( $sv->RV ) eq 'B::GV' ) {
848         $xrvsect->add( "(SV*)Nullgv" );
849         $init->add(sprintf("xrv_list[%d].xrv_rv = (SV*)%s;\n", $xrvsect->index, $rv));
850     }
851     # and stashes, too
852     elsif( $sv->RV->isa( 'B::HV' ) && $sv->RV->NAME ) {
853         $xrvsect->add( "(SV*)Nullhv" );
854         $init->add(sprintf("xrv_list[%d].xrv_rv = (SV*)%s;\n", $xrvsect->index, $rv));
855     }
856     else {
857         $xrvsect->add($rv);
858     }
859     $svsect->add(sprintf("&xrv_list[%d], %lu, 0x%x",
860                          $xrvsect->index, $sv->REFCNT , $sv->FLAGS));
861     return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
862 }
863
864 sub try_autoload {
865     my ($cvstashname, $cvname) = @_;
866     warn sprintf("No definition for sub %s::%s\n", $cvstashname, $cvname);
867     # Handle AutoLoader classes explicitly. Any more general AUTOLOAD
868     # use should be handled by the class itself.
869     no strict 'refs';
870     my $isa = \@{"$cvstashname\::ISA"};
871     if (grep($_ eq "AutoLoader", @$isa)) {
872         warn "Forcing immediate load of sub derived from AutoLoader\n";
873         # Tweaked version of AutoLoader::AUTOLOAD
874         my $dir = $cvstashname;
875         $dir =~ s(::)(/)g;
876         eval { require "auto/$dir/$cvname.al" };
877         if ($@) {
878             warn qq(failed require "auto/$dir/$cvname.al": $@\n);
879             return 0;
880         } else {
881             return 1;
882         }
883     }
884 }
885 sub Dummy_initxs{};
886 sub B::CV::save {
887     my ($cv) = @_;
888     my $sym = objsym($cv);
889     if (defined($sym)) {
890 #       warn sprintf("CV 0x%x already saved as $sym\n", $$cv); # debug
891         return $sym;
892     }
893     # Reserve a place in svsect and xpvcvsect and record indices
894     my $gv = $cv->GV;
895     my ($cvname, $cvstashname);
896     if ($$gv){
897         $cvname = $gv->NAME;
898         $cvstashname = $gv->STASH->NAME;
899     }
900     my $root = $cv->ROOT;
901     my $cvxsub = $cv->XSUB;
902     my $isconst = $cv->CvFLAGS & CVf_CONST;
903     if( $isconst ) {
904         my $value = $cv->XSUBANY;
905         my $stash = $gv->STASH;
906         my $vsym = $value->save;
907         my $stsym = $stash->save;
908         my $name = cstring($cvname);
909         $decl->add( "static CV* cv$cv_index;" );
910         $init->add( "cv$cv_index = newCONSTSUB( $stsym, NULL, $vsym );" );
911         my $sym = savesym( $cv, "cv$cv_index" );
912         $cv_index++;
913         return $sym;
914     }
915     #INIT is removed from the symbol table, so this call must come
916     # from PL_initav->save. Re-bootstrapping  will push INIT back in
917     # so nullop should be sent.
918     if (!$isconst && $cvxsub && ($cvname ne "INIT")) {
919         my $egv = $gv->EGV;
920         my $stashname = $egv->STASH->NAME;
921          if ($cvname eq "bootstrap")
922           { 
923            my $file = $gv->FILE;
924            $decl->add("/* bootstrap $file */"); 
925            warn "Bootstrap $stashname $file\n";
926            # if it not isa('DynaLoader'), it should hopefully be XSLoaded
927            # ( attributes being an exception, of course )
928            if( $stashname ne 'attributes' &&
929                !UNIVERSAL::isa($stashname,'DynaLoader') ) {
930             $xsub{$stashname}='Dynamic-XSLoaded';
931             $use_xsloader = 1;
932            }
933            else {
934             $xsub{$stashname}='Dynamic';
935            }
936            # $xsub{$stashname}='Static' unless  $xsub{$stashname};
937            return qq/NULL/;
938           }
939          else
940           {
941            # XSUBs for IO::File, IO::Handle, IO::Socket,
942            # IO::Seekable and IO::Poll
943            # are defined in IO.xs, so let's bootstrap it
944            svref_2object( \&IO::bootstrap )->save
945             if grep { $stashname eq $_ } qw(IO::File IO::Handle IO::Socket
946                                               IO::Seekable IO::Poll);
947           }
948         warn sprintf("stub for XSUB $cvstashname\:\:$cvname CV 0x%x\n", $$cv) if $debug_cv;
949         return qq/(perl_get_cv("$stashname\:\:$cvname",TRUE))/;
950     }
951     if ($cvxsub && $cvname eq "INIT") {
952          no strict 'refs';
953          return svref_2object(\&Dummy_initxs)->save;
954     }
955     my $sv_ix = $svsect->index + 1;
956     $svsect->add("svix$sv_ix");
957     my $xpvcv_ix = $xpvcvsect->index + 1;
958     $xpvcvsect->add("xpvcvix$xpvcv_ix");
959     # Save symbol now so that GvCV() doesn't recurse back to us via CvGV()
960     $sym = savesym($cv, "&sv_list[$sv_ix]");
961     warn sprintf("saving $cvstashname\:\:$cvname CV 0x%x as $sym\n", $$cv) if $debug_cv;
962     if (!$$root && !$cvxsub) {
963         if (try_autoload($cvstashname, $cvname)) {
964             # Recalculate root and xsub
965             $root = $cv->ROOT;
966             $cvxsub = $cv->XSUB;
967             if ($$root || $cvxsub) {
968                 warn "Successful forced autoload\n";
969             }
970         }
971     }
972     my $startfield = 0;
973     my $padlist = $cv->PADLIST;
974     my $pv = $cv->PV;
975     my $xsub = 0;
976     my $xsubany = "Nullany";
977     if ($$root) {
978         warn sprintf("saving op tree for CV 0x%x, root = 0x%x\n",
979                      $$cv, $$root) if $debug_cv;
980         my $ppname = "";
981         if ($$gv) {
982             my $stashname = $gv->STASH->NAME;
983             my $gvname = $gv->NAME;
984             if ($gvname ne "__ANON__") {
985                 $ppname = (${$gv->FORM} == $$cv) ? "pp_form_" : "pp_sub_";
986                 $ppname .= ($stashname eq "main") ?
987                             $gvname : "$stashname\::$gvname";
988                 $ppname =~ s/::/__/g;
989                 if ($gvname eq "INIT"){
990                        $ppname .= "_$initsub_index";
991                        $initsub_index++;
992                     }
993             }
994         }
995         if (!$ppname) {
996             $ppname = "pp_anonsub_$anonsub_index";
997             $anonsub_index++;
998         }
999         $startfield = saveoptree($ppname, $root, $cv->START, $padlist->ARRAY);
1000         warn sprintf("done saving op tree for CV 0x%x, name %s, root 0x%x\n",
1001                      $$cv, $ppname, $$root) if $debug_cv;
1002         if ($$padlist) {
1003             warn sprintf("saving PADLIST 0x%x for CV 0x%x\n",
1004                          $$padlist, $$cv) if $debug_cv;
1005             $padlist->save;
1006             warn sprintf("done saving PADLIST 0x%x for CV 0x%x\n",
1007                          $$padlist, $$cv) if $debug_cv;
1008         }
1009     }
1010     else {
1011         warn sprintf("No definition for sub %s::%s (unable to autoload)\n",
1012                      $cvstashname, $cvname); # debug
1013     }              
1014     $pv = '' unless defined $pv; # Avoid use of undef warnings
1015     $symsect->add(sprintf("xpvcvix%d\t%s, %u, 0, %d, %s, 0, Nullhv, Nullhv, %s, s\\_%x, $xsub, $xsubany, Nullgv, \"\", %d, s\\_%x, (CV*)s\\_%x, 0x%x, 0x%x",
1016                           $xpvcv_ix, cstring($pv), length($pv), $cv->IVX,
1017                           $cv->NVX, $startfield, ${$cv->ROOT}, $cv->DEPTH,
1018                         $$padlist, ${$cv->OUTSIDE}, $cv->CvFLAGS,
1019                         $cv->OUTSIDE_SEQ));
1020
1021     if (${$cv->OUTSIDE} == ${main_cv()}){
1022         $init->add(sprintf("CvOUTSIDE(s\\_%x)=PL_main_cv;",$$cv));
1023         $init->add(sprintf("SvREFCNT_inc(PL_main_cv);"));
1024     }
1025
1026     if ($$gv) {
1027         $gv->save;
1028         $init->add(sprintf("CvGV(s\\_%x) = s\\_%x;",$$cv,$$gv));
1029         warn sprintf("done saving GV 0x%x for CV 0x%x\n",
1030                      $$gv, $$cv) if $debug_cv;
1031     }
1032     if( $ithreads ) {
1033         $init->add( savepvn( "CvFILE($sym)", $cv->FILE) );
1034     }
1035     else {
1036         $init->add(sprintf("CvFILE($sym) = %s;", cstring($cv->FILE)));
1037     }
1038     my $stash = $cv->STASH;
1039     if ($$stash) {
1040         $stash->save;
1041         $init->add(sprintf("CvSTASH(s\\_%x) = s\\_%x;", $$cv, $$stash));
1042         warn sprintf("done saving STASH 0x%x for CV 0x%x\n",
1043                      $$stash, $$cv) if $debug_cv;
1044     }
1045     $symsect->add(sprintf("svix%d\t(XPVCV*)&xpvcv_list[%u], %lu, 0x%x",
1046                           $sv_ix, $xpvcv_ix, $cv->REFCNT +1*0 , $cv->FLAGS));
1047     return $sym;
1048 }
1049
1050 sub B::GV::save {
1051     my ($gv) = @_;
1052     my $sym = objsym($gv);
1053     if (defined($sym)) {
1054         #warn sprintf("GV 0x%x already saved as $sym\n", $$gv); # debug
1055         return $sym;
1056     } else {
1057         my $ix = $gv_index++;
1058         $sym = savesym($gv, "gv_list[$ix]");
1059         #warn sprintf("Saving GV 0x%x as $sym\n", $$gv); # debug
1060     }
1061     my $is_empty = $gv->is_empty;
1062     my $gvname = $gv->NAME;
1063     my $fullname = $gv->STASH->NAME . "::" . $gvname;
1064     my $name = cstring($fullname);
1065     #warn "GV name is $name\n"; # debug
1066     my $egvsym;
1067     unless ($is_empty) {
1068         my $egv = $gv->EGV;
1069         if ($$gv != $$egv) {
1070             #warn(sprintf("EGV name is %s, saving it now\n",
1071             #        $egv->STASH->NAME . "::" . $egv->NAME)); # debug
1072             $egvsym = $egv->save;
1073         }
1074     }
1075     $init->add(qq[$sym = gv_fetchpv($name, TRUE, SVt_PV);],
1076                sprintf("SvFLAGS($sym) = 0x%x;", $gv->FLAGS ),
1077                sprintf("GvFLAGS($sym) = 0x%x;", $gv->GvFLAGS));
1078     $init->add(sprintf("GvLINE($sym) = %u;", $gv->LINE)) unless $is_empty;
1079     # XXX hack for when Perl accesses PVX of GVs
1080     $init->add("SvPVX($sym) = emptystring;\n");
1081     # Shouldn't need to do save_magic since gv_fetchpv handles that
1082     #$gv->save_magic;
1083     # XXX will always be > 1!!!
1084     my $refcnt = $gv->REFCNT + 1;
1085     $init->add(sprintf("SvREFCNT($sym) += %u;", $refcnt - 1 )) if $refcnt > 1;
1086
1087     return $sym if $is_empty;
1088
1089     # XXX B::walksymtable creates an extra reference to the GV
1090     my $gvrefcnt = $gv->GvREFCNT;
1091     if ($gvrefcnt > 1) {
1092         $init->add(sprintf("GvREFCNT($sym) += %u;", $gvrefcnt - 1));
1093     }
1094     # some non-alphavetic globs require some parts to be saved
1095     # ( ex. %!, but not $! )
1096     sub Save_HV() { 1 }
1097     sub Save_AV() { 2 }
1098     sub Save_SV() { 4 }
1099     sub Save_CV() { 8 }
1100     sub Save_FORM() { 16 }
1101     sub Save_IO() { 32 }
1102     my $savefields = 0;
1103     if( $gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/ ) {
1104         $savefields = Save_HV|Save_AV|Save_SV|Save_CV|Save_FORM|Save_IO;
1105     }
1106     elsif( $gvname eq '!' ) {
1107         $savefields = Save_HV;
1108     }
1109     # attributes::bootstrap is created in perl_parse
1110     # saving it would overwrite it, because perl_init() is
1111     # called after perl_parse()
1112     $savefields&=~Save_CV if $fullname eq 'attributes::bootstrap';
1113
1114     # save it
1115     # XXX is that correct?
1116     if (defined($egvsym) && $egvsym !~ m/Null/ ) {
1117         # Shared glob *foo = *bar
1118         $init->add("gp_free($sym);",
1119                    "GvGP($sym) = GvGP($egvsym);");
1120     } elsif ($savefields) {
1121         # Don't save subfields of special GVs (*_, *1, *# and so on)
1122 #       warn "GV::save saving subfields\n"; # debug
1123         my $gvsv = $gv->SV;
1124         if ($$gvsv && $savefields&Save_SV) {
1125             $gvsv->save;
1126             $init->add(sprintf("GvSV($sym) = s\\_%x;", $$gvsv));
1127 #           warn "GV::save \$$name\n"; # debug
1128         }
1129         my $gvav = $gv->AV;
1130         if ($$gvav && $savefields&Save_AV) {
1131             $gvav->save;
1132             $init->add(sprintf("GvAV($sym) = s\\_%x;", $$gvav));
1133 #           warn "GV::save \@$name\n"; # debug
1134         }
1135         my $gvhv = $gv->HV;
1136         if ($$gvhv && $savefields&Save_HV) {
1137             $gvhv->save;
1138             $init->add(sprintf("GvHV($sym) = s\\_%x;", $$gvhv));
1139 #           warn "GV::save \%$name\n"; # debug
1140         }
1141         my $gvcv = $gv->CV;
1142         if ($$gvcv && $savefields&Save_CV) {
1143             my $origname=cstring($gvcv->GV->EGV->STASH->NAME .
1144                  "::" . $gvcv->GV->EGV->NAME);  
1145             if (0 && $gvcv->XSUB && $name ne $origname) { #XSUB alias
1146                 # must save as a 'stub' so newXS() has a CV to populate
1147                 $init->add("{ CV *cv;");
1148                 $init->add("\tcv=perl_get_cv($origname,TRUE);");
1149                 $init->add("\tGvCV($sym)=cv;");
1150                 $init->add("\tSvREFCNT_inc((SV *)cv);");
1151                 $init->add("}");    
1152             } else {
1153                $init->add(sprintf("GvCV($sym) = (CV*)(%s);", $gvcv->save));
1154 #              warn "GV::save &$name\n"; # debug
1155             } 
1156         }     
1157         $init->add(sprintf("GvFILE($sym) = %s;", cstring($gv->FILE)));
1158 #       warn "GV::save GvFILE(*$name)\n"; # debug
1159         my $gvform = $gv->FORM;
1160         if ($$gvform && $savefields&Save_FORM) {
1161             $gvform->save;
1162             $init->add(sprintf("GvFORM($sym) = (CV*)s\\_%x;", $$gvform));
1163 #           warn "GV::save GvFORM(*$name)\n"; # debug
1164         }
1165         my $gvio = $gv->IO;
1166         if ($$gvio && $savefields&Save_IO) {
1167             $gvio->save;
1168             $init->add(sprintf("GvIOp($sym) = s\\_%x;", $$gvio));
1169             if( $fullname =~ m/::DATA$/ && $save_data_fh ) {
1170                 no strict 'refs';
1171                 my $fh = *{$fullname}{IO};
1172                 use strict 'refs';
1173                 $gvio->save_data( $fullname, <$fh> ) if $fh->opened;
1174             }
1175 #           warn "GV::save GvIO(*$name)\n"; # debug
1176         }
1177     }
1178     return $sym;
1179 }
1180
1181 sub B::AV::save {
1182     my ($av) = @_;
1183     my $sym = objsym($av);
1184     return $sym if defined $sym;
1185     my $avflags = $av->AvFLAGS;
1186     $xpvavsect->add(sprintf("0, -1, -1, 0, 0.0, 0, Nullhv, 0, 0, 0x%x",
1187                             $avflags));
1188     $svsect->add(sprintf("&xpvav_list[%d], %lu, 0x%x",
1189                          $xpvavsect->index, $av->REFCNT  , $av->FLAGS));
1190     my $sv_list_index = $svsect->index;
1191     my $fill = $av->FILL;
1192     $av->save_magic;
1193     warn sprintf("saving AV 0x%x FILL=$fill AvFLAGS=0x%x", $$av, $avflags)
1194         if $debug_av;
1195     # XXX AVf_REAL is wrong test: need to save comppadlist but not stack
1196     #if ($fill > -1 && ($avflags & AVf_REAL)) {
1197     if ($fill > -1) {
1198         my @array = $av->ARRAY;
1199         if ($debug_av) {
1200             my $el;
1201             my $i = 0;
1202             foreach $el (@array) {
1203                 warn sprintf("AV 0x%x[%d] = %s 0x%x\n",
1204                              $$av, $i++, class($el), $$el);
1205             }
1206         }
1207 #       my @names = map($_->save, @array);
1208         # XXX Better ways to write loop?
1209         # Perhaps svp[0] = ...; svp[1] = ...; svp[2] = ...;
1210         # Perhaps I32 i = 0; svp[i++] = ...; svp[i++] = ...; svp[i++] = ...;
1211
1212         # micro optimization: op/pat.t ( and other code probably )
1213         # has very large pads ( 20k/30k elements ) passing them to
1214         # ->add is a performance bottleneck: passing them as a
1215         # single string cuts runtime from 6min20sec to 40sec
1216
1217         # you want to keep this out of the no_split/split
1218         # map("\t*svp++ = (SV*)$_;", @names),
1219         my $acc = '';
1220         foreach my $i ( 0..$#array ) {
1221               $acc .= "\t*svp++ = (SV*)" . $array[$i]->save . ";\n\t";
1222         }
1223         $acc .= "\n";
1224
1225         $init->no_split;
1226         $init->add("{",
1227                    "\tSV **svp;",
1228                    "\tAV *av = (AV*)&sv_list[$sv_list_index];",
1229                    "\tav_extend(av, $fill);",
1230                    "\tsvp = AvARRAY(av);" );
1231         $init->add($acc);
1232         $init->add("\tAvFILLp(av) = $fill;",
1233                    "}");
1234         $init->split;
1235         # we really added a lot of lines ( B::C::InitSection->add
1236         # should really scan for \n, but that would slow
1237         # it down
1238         $init->inc_count( $#array );
1239     } else {
1240         my $max = $av->MAX;
1241         $init->add("av_extend((AV*)&sv_list[$sv_list_index], $max);")
1242             if $max > -1;
1243     }
1244     return savesym($av, "(AV*)&sv_list[$sv_list_index]");
1245 }
1246
1247 sub B::HV::save {
1248     my ($hv) = @_;
1249     my $sym = objsym($hv);
1250     return $sym if defined $sym;
1251     my $name = $hv->NAME;
1252     if ($name) {
1253         # It's a stash
1254
1255         # A perl bug means HvPMROOT isn't altered when a PMOP is freed. Usually
1256         # the only symptom is that sv_reset tries to reset the PMf_USED flag of
1257         # a trashed op but we look at the trashed op_type and segfault.
1258         #my $adpmroot = ${$hv->PMROOT};
1259         my $adpmroot = 0;
1260         $decl->add("static HV *hv$hv_index;");
1261         # XXX Beware of weird package names containing double-quotes, \n, ...?
1262         $init->add(qq[hv$hv_index = gv_stashpv("$name", TRUE);]);
1263         if ($adpmroot) {
1264             $init->add(sprintf("HvPMROOT(hv$hv_index) = (PMOP*)s\\_%x;",
1265                                $adpmroot));
1266         }
1267         $sym = savesym($hv, "hv$hv_index");
1268         $hv_index++;
1269         return $sym;
1270     }
1271     # It's just an ordinary HV
1272     $xpvhvsect->add(sprintf("0, 0, %d, 0, 0.0, 0, Nullhv, %d, 0, 0, 0",
1273                             $hv->MAX, $hv->RITER));
1274     $svsect->add(sprintf("&xpvhv_list[%d], %lu, 0x%x",
1275                          $xpvhvsect->index, $hv->REFCNT  , $hv->FLAGS));
1276     my $sv_list_index = $svsect->index;
1277     my @contents = $hv->ARRAY;
1278     if (@contents) {
1279         my $i;
1280         for ($i = 1; $i < @contents; $i += 2) {
1281             $contents[$i] = $contents[$i]->save;
1282         }
1283         $init->no_split;
1284         $init->add("{", "\tHV *hv = (HV*)&sv_list[$sv_list_index];");
1285         while (@contents) {
1286             my ($key, $value) = splice(@contents, 0, 2);
1287             $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1288                                cstring($key),length(pack "a*",$key),
1289                                $value, hash($key)));
1290 #           $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1291 #                              cstring($key),length($key),$value, 0));
1292         }
1293         $init->add("}");
1294         $init->split;
1295     }
1296     $hv->save_magic();
1297     return savesym($hv, "(HV*)&sv_list[$sv_list_index]");
1298 }
1299
1300 sub B::IO::save_data {
1301     my( $io, $globname, @data ) = @_;
1302     my $data = join '', @data;
1303
1304     # XXX using $DATA might clobber it!
1305     my $sym = svref_2object( \\$data )->save;
1306     $init->add( split /\n/, <<CODE );
1307     {
1308         GV* gv = (GV*)gv_fetchpv( "$globname", TRUE, SVt_PV );
1309         SV* sv = $sym;
1310         GvSV( gv ) = sv;
1311     }
1312 CODE
1313     # for PerlIO::scalar
1314     $use_xsloader = 1;
1315     $init->add_eval( sprintf 'open(%s, "<", $%s)', $globname, $globname );
1316 }
1317
1318 sub B::IO::save {
1319     my ($io) = @_;
1320     my $sym = objsym($io);
1321     return $sym if defined $sym;
1322     my $pv = $io->PV;
1323     $pv = '' unless defined $pv;
1324     my $len = length($pv);
1325     $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",
1326                             $len, $len+1, $io->IVX, $io->NVX, $io->LINES,
1327                             $io->PAGE, $io->PAGE_LEN, $io->LINES_LEFT,
1328                             cstring($io->TOP_NAME), cstring($io->FMT_NAME), 
1329                             cstring($io->BOTTOM_NAME), $io->SUBPROCESS,
1330                             cchar($io->IoTYPE), $io->IoFLAGS));
1331     $svsect->add(sprintf("&xpvio_list[%d], %lu, 0x%x",
1332                          $xpviosect->index, $io->REFCNT , $io->FLAGS));
1333     $sym = savesym($io, sprintf("(IO*)&sv_list[%d]", $svsect->index));
1334     # deal with $x = *STDIN/STDOUT/STDERR{IO}
1335     my $perlio_func;
1336     foreach ( qw(stdin stdout stderr) ) {
1337         $io->IsSTD($_) and $perlio_func = $_;
1338     }
1339     if( $perlio_func ) {
1340         $init->add( "IoIFP(${sym})=PerlIO_${perlio_func}();" );
1341         $init->add( "IoOFP(${sym})=PerlIO_${perlio_func}();" );
1342     }
1343
1344     my ($field, $fsym);
1345     foreach $field (qw(TOP_GV FMT_GV BOTTOM_GV)) {
1346         $fsym = $io->$field();
1347         if ($$fsym) {
1348             $init->add(sprintf("Io$field($sym) = (GV*)s\\_%x;", $$fsym));
1349             $fsym->save;
1350         }
1351     }
1352     $io->save_magic;
1353     return $sym;
1354 }
1355
1356 sub B::SV::save {
1357     my $sv = shift;
1358     # This is where we catch an honest-to-goodness Nullsv (which gets
1359     # blessed into B::SV explicitly) and any stray erroneous SVs.
1360     return 0 unless $$sv;
1361     confess sprintf("cannot save that type of SV: %s (0x%x)\n",
1362                     class($sv), $$sv);
1363 }
1364
1365 sub output_all {
1366     my $init_name = shift;
1367     my $section;
1368     my @sections = ($opsect, $unopsect, $binopsect, $logopsect, $condopsect,
1369                     $listopsect, $pmopsect, $svopsect, $padopsect, $pvopsect,
1370                     $loopsect, $copsect, $svsect, $xpvsect,
1371                     $xpvavsect, $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect,
1372                     $xpvmgsect, $xpvlvsect, $xrvsect, $xpvbmsect, $xpviosect);
1373     $symsect->output(\*STDOUT, "#define %s\n");
1374     print "\n";
1375     output_declarations();
1376     foreach $section (@sections) {
1377         my $lines = $section->index + 1;
1378         if ($lines) {
1379             my $name = $section->name;
1380             my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
1381             print "Static $typename ${name}_list[$lines];\n";
1382         }
1383     }
1384     # XXX hack for when Perl accesses PVX of GVs
1385     print 'Static char emptystring[] = "\0";';
1386
1387     $decl->output(\*STDOUT, "%s\n");
1388     print "\n";
1389     foreach $section (@sections) {
1390         my $lines = $section->index + 1;
1391         if ($lines) {
1392             my $name = $section->name;
1393             my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
1394             printf "static %s %s_list[%u] = {\n", $typename, $name, $lines;
1395             $section->output(\*STDOUT, "\t{ %s }, /* %d */\n");
1396             print "};\n\n";
1397         }
1398     }
1399
1400     $init->output(\*STDOUT, "\t%s\n", $init_name );
1401     if ($verbose) {
1402         warn compile_stats();
1403         warn "NULLOP count: $nullop_count\n";
1404     }
1405 }
1406
1407 sub output_declarations {
1408     print <<'EOT';
1409 #ifdef BROKEN_STATIC_REDECL
1410 #define Static extern
1411 #else
1412 #define Static static
1413 #endif /* BROKEN_STATIC_REDECL */
1414
1415 #ifdef BROKEN_UNION_INIT
1416 /*
1417  * Cribbed from cv.h with ANY (a union) replaced by void*.
1418  * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
1419  */
1420 typedef struct {
1421     char *      xpv_pv;         /* pointer to malloced string */
1422     STRLEN      xpv_cur;        /* length of xp_pv as a C string */
1423     STRLEN      xpv_len;        /* allocated size */
1424     IV          xof_off;        /* integer value */
1425     NV          xnv_nv;         /* numeric value, if any */
1426     MAGIC*      xmg_magic;      /* magic for scalar array */
1427     HV*         xmg_stash;      /* class package */
1428
1429     HV *        xcv_stash;
1430     OP *        xcv_start;
1431     OP *        xcv_root;
1432     void      (*xcv_xsub) (pTHX_ CV*);
1433     ANY         xcv_xsubany;
1434     GV *        xcv_gv;
1435     char *      xcv_file;
1436     long        xcv_depth;      /* >= 2 indicates recursive call */
1437     AV *        xcv_padlist;
1438     CV *        xcv_outside;
1439 EOT
1440     print <<'EOT' if $] < 5.009;
1441 #ifdef USE_5005THREADS
1442     perl_mutex *xcv_mutexp;
1443     struct perl_thread *xcv_owner;      /* current owner thread */
1444 #endif /* USE_5005THREADS */
1445 EOT
1446     print <<'EOT';
1447     cv_flags_t  xcv_flags;
1448     U32         xcv_outside_seq; /* the COP sequence (at the point of our
1449                                   * compilation) in the lexically enclosing
1450                                   * sub */
1451 } XPVCV_or_similar;
1452 #define ANYINIT(i) i
1453 #else
1454 #define XPVCV_or_similar XPVCV
1455 #define ANYINIT(i) {i}
1456 #endif /* BROKEN_UNION_INIT */
1457 #define Nullany ANYINIT(0)
1458
1459 #define UNUSED 0
1460 #define sym_0 0
1461 EOT
1462     print "static GV *gv_list[$gv_index];\n" if $gv_index;
1463     print "\n";
1464 }
1465
1466
1467 sub output_boilerplate {
1468     print <<'EOT';
1469 #include "EXTERN.h"
1470 #include "perl.h"
1471 #include "XSUB.h"
1472
1473 /* Workaround for mapstart: the only op which needs a different ppaddr */
1474 #undef Perl_pp_mapstart
1475 #define Perl_pp_mapstart Perl_pp_grepstart
1476 #undef OP_MAPSTART
1477 #define OP_MAPSTART OP_GREPSTART
1478 #define XS_DynaLoader_boot_DynaLoader boot_DynaLoader
1479 EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
1480
1481 static void xs_init (pTHX);
1482 static void dl_init (pTHX);
1483 static PerlInterpreter *my_perl;
1484 EOT
1485 }
1486
1487 sub init_op_addr {
1488     my( $op_type, $num ) = @_;
1489     my $op_list = $op_type."_list";
1490
1491     $init->add( split /\n/, <<EOT );
1492     {
1493         int i;
1494
1495         for( i = 0; i < ${num}; ++i )
1496         {
1497             ${op_list}\[i].op_ppaddr = PL_ppaddr[INT2PTR(int,${op_list}\[i].op_ppaddr)];
1498         }
1499     }
1500 EOT
1501 }
1502
1503 sub init_op_warn {
1504     my( $op_type, $num ) = @_;
1505     my $op_list = $op_type."_list";
1506
1507     # for resons beyond imagination, MSVC5 considers pWARN_ALL non-const
1508     $init->add( split /\n/, <<EOT );
1509     {
1510         int i;
1511
1512         for( i = 0; i < ${num}; ++i )
1513         {
1514             switch( (int)(${op_list}\[i].cop_warnings) )
1515             {
1516             case 1:
1517                 ${op_list}\[i].cop_warnings = pWARN_ALL;
1518                 break;
1519             case 2:
1520                 ${op_list}\[i].cop_warnings = pWARN_NONE;
1521                 break;
1522             case 3:
1523                 ${op_list}\[i].cop_warnings = pWARN_STD;
1524                 break;
1525             default:
1526                 break;
1527             }
1528         }
1529     }
1530 EOT
1531 }
1532
1533 sub output_main {
1534     print <<'EOT';
1535 /* if USE_IMPLICIT_SYS, we need a 'real' exit */
1536 #if defined(exit)
1537 #undef exit
1538 #endif
1539
1540 int
1541 main(int argc, char **argv, char **env)
1542 {
1543     int exitstatus;
1544     int i;
1545     char **fakeargv;
1546     GV* tmpgv;
1547     SV* tmpsv;
1548     int options_count;
1549
1550     PERL_SYS_INIT3(&argc,&argv,&env);
1551
1552     if (!PL_do_undump) {
1553         my_perl = perl_alloc();
1554         if (!my_perl)
1555             exit(1);
1556         perl_construct( my_perl );
1557         PL_perl_destruct_level = 0;
1558     }
1559 EOT
1560     if( $ithreads ) {
1561         # XXX init free elems!
1562         my $pad_len = regex_padav->FILL + 1 - 1; # first is an avref
1563
1564         print <<EOT;
1565 #ifdef USE_ITHREADS
1566     for( i = 0; i < $pad_len; ++i ) {
1567         av_push( PL_regex_padav, newSViv(0) );
1568     }
1569     PL_regex_pad = AvARRAY( PL_regex_padav );
1570 #endif
1571 EOT
1572     }
1573
1574     print <<'EOT';
1575 #ifdef CSH
1576     if (!PL_cshlen) 
1577       PL_cshlen = strlen(PL_cshname);
1578 #endif
1579
1580 #ifdef ALLOW_PERL_OPTIONS
1581 #define EXTRA_OPTIONS 3
1582 #else
1583 #define EXTRA_OPTIONS 4
1584 #endif /* ALLOW_PERL_OPTIONS */
1585     New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
1586
1587     fakeargv[0] = argv[0];
1588     fakeargv[1] = "-e";
1589     fakeargv[2] = "";
1590     options_count = 3;
1591 EOT
1592     # honour -T
1593     print <<EOT;
1594     if( ${^TAINT} ) {
1595         fakeargv[options_count] = "-T";
1596         ++options_count;
1597     }
1598 EOT
1599     print <<'EOT';
1600 #ifndef ALLOW_PERL_OPTIONS
1601     fakeargv[options_count] = "--";
1602     ++options_count;
1603 #endif /* ALLOW_PERL_OPTIONS */
1604     for (i = 1; i < argc; i++)
1605         fakeargv[i + options_count - 1] = argv[i];
1606     fakeargv[argc + options_count - 1] = 0;
1607
1608     exitstatus = perl_parse(my_perl, xs_init, argc + options_count - 1,
1609                             fakeargv, NULL);
1610
1611     if (exitstatus)
1612         exit( exitstatus );
1613
1614     TAINT;
1615 EOT
1616
1617     if( $use_perl_script_name ) {
1618         my $dollar_0 = $0;
1619         $dollar_0 =~ s/\\/\\\\/g;
1620         $dollar_0 = '"' . $dollar_0 . '"';
1621
1622         print <<EOT;
1623     if ((tmpgv = gv_fetchpv("0",TRUE, SVt_PV))) {/* $0 */
1624         tmpsv = GvSV(tmpgv);
1625         sv_setpv(tmpsv, ${dollar_0});
1626         SvSETMAGIC(tmpsv);
1627     }
1628 EOT
1629     }
1630     else {
1631         print <<EOT;
1632     if ((tmpgv = gv_fetchpv("0",TRUE, SVt_PV))) {/* $0 */
1633         tmpsv = GvSV(tmpgv);
1634         sv_setpv(tmpsv, argv[0]);
1635         SvSETMAGIC(tmpsv);
1636     }
1637 EOT
1638     }
1639
1640     print <<'EOT';
1641     if ((tmpgv = gv_fetchpv("\030",TRUE, SVt_PV))) {/* $^X */
1642         tmpsv = GvSV(tmpgv);
1643 #ifdef WIN32
1644         sv_setpv(tmpsv,"perl.exe");
1645 #else
1646         sv_setpv(tmpsv,"perl");
1647 #endif
1648         SvSETMAGIC(tmpsv);
1649     }
1650
1651     TAINT_NOT;
1652
1653     /* PL_main_cv = PL_compcv; */
1654     PL_compcv = 0;
1655
1656     exitstatus = perl_init();
1657     if (exitstatus)
1658         exit( exitstatus );
1659     dl_init(aTHX);
1660
1661     exitstatus = perl_run( my_perl );
1662
1663     perl_destruct( my_perl );
1664     perl_free( my_perl );
1665
1666     PERL_SYS_TERM();
1667
1668     exit( exitstatus );
1669 }
1670
1671 /* yanked from perl.c */
1672 static void
1673 xs_init(pTHX)
1674 {
1675     char *file = __FILE__;
1676     dTARG;
1677     dSP;
1678 EOT
1679     print "\n#ifdef USE_DYNAMIC_LOADING";
1680     print qq/\n\tnewXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);/;
1681     print "\n#endif\n" ;
1682     # delete $xsub{'DynaLoader'}; 
1683     delete $xsub{'UNIVERSAL'}; 
1684     print("/* bootstrapping code*/\n\tSAVETMPS;\n");
1685     print("\ttarg=sv_newmortal();\n");
1686     print "#ifdef USE_DYNAMIC_LOADING\n";
1687     print "\tPUSHMARK(sp);\n";
1688     print qq/\tXPUSHp("DynaLoader",strlen("DynaLoader"));\n/;
1689     print qq/\tPUTBACK;\n/;
1690     print "\tboot_DynaLoader(aTHX_ NULL);\n";
1691     print qq/\tSPAGAIN;\n/;
1692     print "#endif\n";
1693     foreach my $stashname (keys %xsub){
1694         if ($xsub{$stashname} !~ m/Dynamic/ ) {
1695            my $stashxsub=$stashname;
1696            $stashxsub  =~ s/::/__/g; 
1697            print "\tPUSHMARK(sp);\n";
1698            print qq/\tXPUSHp("$stashname",strlen("$stashname"));\n/;
1699            print qq/\tPUTBACK;\n/;
1700            print "\tboot_$stashxsub(aTHX_ NULL);\n";
1701            print qq/\tSPAGAIN;\n/;
1702         }   
1703     }
1704     print("\tFREETMPS;\n/* end bootstrapping code */\n");
1705     print "}\n";
1706     
1707 print <<'EOT';
1708 static void
1709 dl_init(pTHX)
1710 {
1711     char *file = __FILE__;
1712     dTARG;
1713     dSP;
1714 EOT
1715     print("/* Dynamicboot strapping code*/\n\tSAVETMPS;\n");
1716     print("\ttarg=sv_newmortal();\n");
1717     foreach my $stashname (@DynaLoader::dl_modules) {
1718         warn "Loaded $stashname\n";
1719         if (exists($xsub{$stashname}) && $xsub{$stashname} =~ m/Dynamic/) {
1720            my $stashxsub=$stashname;
1721            $stashxsub  =~ s/::/__/g; 
1722            print "\tPUSHMARK(sp);\n";
1723            print qq/\tXPUSHp("$stashname",/,length($stashname),qq/);\n/;
1724            print qq/\tPUTBACK;\n/;
1725            print "#ifdef USE_DYNAMIC_LOADING\n";
1726            warn "bootstrapping $stashname added to xs_init\n";
1727            if( $xsub{$stashname} eq 'Dynamic' ) {
1728               print qq/\tperl_call_method("bootstrap",G_DISCARD);\n/;
1729            }
1730            else {
1731               print qq/\tperl_call_pv("XSLoader::load",G_DISCARD);\n/;
1732            }
1733            print "#else\n";
1734            print "\tboot_$stashxsub(aTHX_ NULL);\n";
1735            print "#endif\n";
1736            print qq/\tSPAGAIN;\n/;
1737         }   
1738     }
1739     print("\tFREETMPS;\n/* end Dynamic bootstrapping code */\n");
1740     print "}\n";
1741 }
1742 sub dump_symtable {
1743     # For debugging
1744     my ($sym, $val);
1745     warn "----Symbol table:\n";
1746     while (($sym, $val) = each %symtable) {
1747         warn "$sym => $val\n";
1748     }
1749     warn "---End of symbol table\n";
1750 }
1751
1752 sub save_object {
1753     my $sv;
1754     foreach $sv (@_) {
1755         svref_2object($sv)->save;
1756     }
1757 }       
1758
1759 sub Dummy_BootStrap { }            
1760
1761 sub B::GV::savecv 
1762 {
1763  my $gv = shift;
1764  my $package=$gv->STASH->NAME;
1765  my $name = $gv->NAME;
1766  my $cv = $gv->CV;
1767  my $sv = $gv->SV;
1768  my $av = $gv->AV;
1769  my $hv = $gv->HV;
1770
1771  my $fullname = $gv->STASH->NAME . "::" . $gv->NAME;
1772
1773  # We may be looking at this package just because it is a branch in the 
1774  # symbol table which is on the path to a package which we need to save
1775  # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
1776  # 
1777  return unless ($unused_sub_packages{$package});
1778  return unless ($$cv || $$av || $$sv || $$hv);
1779  $gv->save;
1780 }
1781
1782 sub mark_package
1783 {    
1784  my $package = shift;
1785  unless ($unused_sub_packages{$package})
1786   {    
1787    no strict 'refs';
1788    $unused_sub_packages{$package} = 1;
1789    if (defined @{$package.'::ISA'})
1790     {
1791      foreach my $isa (@{$package.'::ISA'}) 
1792       {
1793        if ($isa eq 'DynaLoader')
1794         {
1795          unless (defined(&{$package.'::bootstrap'}))
1796           {                    
1797            warn "Forcing bootstrap of $package\n";
1798            eval { $package->bootstrap }; 
1799           }
1800         }
1801 #      else
1802         {
1803          unless ($unused_sub_packages{$isa})
1804           {
1805            warn "$isa saved (it is in $package\'s \@ISA)\n";
1806            mark_package($isa);
1807           }
1808         }
1809       }
1810     }
1811   }
1812  return 1;
1813 }
1814      
1815 sub should_save
1816 {
1817  no strict qw(vars refs);
1818  my $package = shift;
1819  $package =~ s/::$//;
1820  return $unused_sub_packages{$package} = 0 if ($package =~ /::::/);  # skip ::::ISA::CACHE etc.
1821  # warn "Considering $package\n";#debug
1822  foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages)) 
1823   {  
1824    # If this package is a prefix to something we are saving, traverse it 
1825    # but do not mark it for saving if it is not already
1826    # e.g. to get to Getopt::Long we need to traverse Getopt but need
1827    # not save Getopt
1828    return 1 if ($u =~ /^$package\:\:/);
1829   }
1830  if (exists $unused_sub_packages{$package})
1831   {
1832    # warn "Cached $package is ".$unused_sub_packages{$package}."\n"; 
1833    delete_unsaved_hashINC($package) unless  $unused_sub_packages{$package} ;
1834    return $unused_sub_packages{$package}; 
1835   }
1836  # Omit the packages which we use (and which cause grief
1837  # because of fancy "goto &$AUTOLOAD" stuff).
1838  # XXX Surely there must be a nicer way to do this.
1839  if ($package eq "FileHandle" || $package eq "Config" || 
1840      $package eq "SelectSaver" || $package =~/^(B|IO)::/) 
1841   {
1842    delete_unsaved_hashINC($package);
1843    return $unused_sub_packages{$package} = 0;
1844   }
1845  # Now see if current package looks like an OO class this is probably too strong.
1846  foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE)) 
1847   {
1848    if (UNIVERSAL::can($package, $m))
1849     {
1850      warn "$package has method $m: saving package\n";#debug
1851      return mark_package($package);
1852     }
1853   }
1854  delete_unsaved_hashINC($package);
1855  return $unused_sub_packages{$package} = 0;
1856 }
1857 sub delete_unsaved_hashINC{
1858         my $packname=shift;
1859         $packname =~ s/\:\:/\//g;
1860         $packname .= '.pm';
1861 #       warn "deleting $packname" if $INC{$packname} ;# debug
1862         delete $INC{$packname};
1863 }
1864 sub walkpackages 
1865 {
1866  my ($symref, $recurse, $prefix) = @_;
1867  my $sym;
1868  my $ref;
1869  no strict 'vars';
1870  $prefix = '' unless defined $prefix;
1871  while (($sym, $ref) = each %$symref) 
1872   {             
1873    local(*glob);
1874    *glob = $ref;
1875    if ($sym =~ /::$/) 
1876     {
1877      $sym = $prefix . $sym;
1878      if ($sym ne "main::" && $sym ne "<none>::" && &$recurse($sym)) 
1879       {
1880        walkpackages(\%glob, $recurse, $sym);
1881       }
1882     } 
1883   }
1884 }
1885
1886
1887 sub save_unused_subs 
1888 {
1889  no strict qw(refs);
1890  &descend_marked_unused;
1891  warn "Prescan\n";
1892  walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
1893  warn "Saving methods\n";
1894  walksymtable(\%{"main::"}, "savecv", \&should_save);
1895 }
1896
1897 sub save_context
1898 {
1899  my $curpad_nam = (comppadlist->ARRAY)[0]->save;
1900  my $curpad_sym = (comppadlist->ARRAY)[1]->save;
1901  my $inc_hv     = svref_2object(\%INC)->save;
1902  my $inc_av     = svref_2object(\@INC)->save;
1903  my $amagic_generate= amagic_generation;          
1904  $init->add(   "PL_curpad = AvARRAY($curpad_sym);",
1905                "GvHV(PL_incgv) = $inc_hv;",
1906                "GvAV(PL_incgv) = $inc_av;",
1907                "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
1908                "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
1909                 "PL_amagic_generation= $amagic_generate;" );
1910 }
1911
1912 sub descend_marked_unused {
1913     foreach my $pack (keys %unused_sub_packages)
1914     {
1915         mark_package($pack);
1916     }
1917 }
1918  
1919 sub save_main {
1920     # this is mainly for the test suite
1921     my $warner = $SIG{__WARN__};
1922     local $SIG{__WARN__} = sub { print STDERR @_ };
1923
1924     warn "Starting compile\n";
1925     warn "Walking tree\n";
1926     seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
1927     walkoptree(main_root, "save");
1928     warn "done main optree, walking symtable for extras\n" if $debug_cv;
1929     save_unused_subs();
1930     # XSLoader was used, force saving of XSLoader::load
1931     if( $use_xsloader ) {
1932         my $cv = svref_2object( \&XSLoader::load );
1933         $cv->save;
1934     }
1935     # save %SIG ( in case it was set in a BEGIN block )
1936     if( $save_sig ) {
1937         local $SIG{__WARN__} = $warner;
1938         $init->no_split;
1939         $init->add("{", "\tHV* hv = get_hv(\"main::SIG\",1);" );
1940         foreach my $k ( keys %SIG ) {
1941             next unless ref $SIG{$k};
1942             my $cv = svref_2object( \$SIG{$k} );
1943             my $sv = $cv->save;
1944             $init->add('{',sprintf 'SV* sv = (SV*)%s;', $sv );
1945             $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1946                                cstring($k),length(pack "a*",$k),
1947                                'sv', hash($k)));
1948             $init->add('mg_set(sv);','}');
1949         }
1950         $init->add('}');
1951         $init->split;
1952     }
1953     # honour -w
1954     $init->add( sprintf "    PL_dowarn = ( %s ) ? G_WARN_ON : G_WARN_OFF;", $^W );
1955     #
1956     my $init_av = init_av->save;
1957     my $end_av = end_av->save;
1958     $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1959                sprintf("PL_main_start = s\\_%x;", ${main_start()}),
1960               "PL_initav = (AV *) $init_av;",
1961               "PL_endav = (AV*) $end_av;");
1962     save_context();
1963     # init op addrs ( must be the last action, otherwise
1964     # some ops might not be initialized
1965     if( $optimize_ppaddr ) {
1966         foreach my $i ( @op_sections ) {
1967             my $section = $$i;
1968             next unless $section->index >= 0;
1969             init_op_addr( $section->name, $section->index + 1);
1970         }
1971     }
1972     init_op_warn( $copsect->name, $copsect->index + 1)
1973       if $optimize_warn_sv && $copsect->index >= 0;
1974
1975     warn "Writing output\n";
1976     output_boilerplate();
1977     print "\n";
1978     output_all("perl_init");
1979     print "\n";
1980     output_main();
1981 }
1982
1983 sub init_sections {
1984     my @sections = (decl => \$decl, sym => \$symsect,
1985                     binop => \$binopsect, condop => \$condopsect,
1986                     cop => \$copsect, padop => \$padopsect,
1987                     listop => \$listopsect, logop => \$logopsect,
1988                     loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
1989                     pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
1990                     sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
1991                     xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
1992                     xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
1993                     xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
1994                     xrv => \$xrvsect, xpvbm => \$xpvbmsect,
1995                     xpvio => \$xpviosect);
1996     my ($name, $sectref);
1997     while (($name, $sectref) = splice(@sections, 0, 2)) {
1998         $$sectref = new B::C::Section $name, \%symtable, 0;
1999     }
2000     $init = new B::C::InitSection 'init', \%symtable, 0;
2001 }
2002
2003 sub mark_unused
2004 {
2005  my ($arg,$val) = @_;
2006  $unused_sub_packages{$arg} = $val;
2007 }
2008
2009 sub compile {
2010     my @options = @_;
2011     my ($option, $opt, $arg);
2012     my @eval_at_startup;
2013     my %option_map = ( 'cog' => \$pv_copy_on_grow,
2014                        'save-data' => \$save_data_fh,
2015                        'ppaddr' => \$optimize_ppaddr,
2016                        'warn-sv' => \$optimize_warn_sv,
2017                        'use-script-name' => \$use_perl_script_name,
2018                        'save-sig-hash' => \$save_sig,
2019                      );
2020     my %optimization_map = ( 0 => [ qw() ], # special case
2021                              1 => [ qw(-fcog) ],
2022                              2 => [ qw(-fwarn-sv -fppaddr) ],
2023                            );
2024   OPTION:
2025     while ($option = shift @options) {
2026         if ($option =~ /^-(.)(.*)/) {
2027             $opt = $1;
2028             $arg = $2;
2029         } else {
2030             unshift @options, $option;
2031             last OPTION;
2032         }
2033         if ($opt eq "-" && $arg eq "-") {
2034             shift @options;
2035             last OPTION;
2036         }
2037         if ($opt eq "w") {
2038             $warn_undefined_syms = 1;
2039         } elsif ($opt eq "D") {
2040             $arg ||= shift @options;
2041             foreach $arg (split(//, $arg)) {
2042                 if ($arg eq "o") {
2043                     B->debug(1);
2044                 } elsif ($arg eq "c") {
2045                     $debug_cops = 1;
2046                 } elsif ($arg eq "A") {
2047                     $debug_av = 1;
2048                 } elsif ($arg eq "C") {
2049                     $debug_cv = 1;
2050                 } elsif ($arg eq "M") {
2051                     $debug_mg = 1;
2052                 } else {
2053                     warn "ignoring unknown debug option: $arg\n";
2054                 }
2055             }
2056         } elsif ($opt eq "o") {
2057             $arg ||= shift @options;
2058             open(STDOUT, ">$arg") or return "$arg: $!\n";
2059         } elsif ($opt eq "v") {
2060             $verbose = 1;
2061         } elsif ($opt eq "u") {
2062             $arg ||= shift @options;
2063             mark_unused($arg,undef);
2064         } elsif ($opt eq "f") {
2065             $arg ||= shift @options;
2066             $arg =~ m/(no-)?(.*)/;
2067             my $no = defined($1) && $1 eq 'no-';
2068             $arg = $no ? $2 : $arg;
2069             if( exists $option_map{$arg} ) {
2070                 ${$option_map{$arg}} = !$no;
2071             } else {
2072                 die "Invalid optimization '$arg'";
2073             }
2074         } elsif ($opt eq "O") {
2075             $arg = 1 if $arg eq "";
2076             my @opt;
2077             foreach my $i ( 1 .. $arg ) {
2078                 push @opt, @{$optimization_map{$i}}
2079                     if exists $optimization_map{$i};
2080             }
2081             unshift @options, @opt;
2082         } elsif ($opt eq "e") {
2083             push @eval_at_startup, $arg;
2084         } elsif ($opt eq "l") {
2085             $max_string_len = $arg;
2086         }
2087     }
2088     init_sections();
2089     foreach my $i ( @eval_at_startup ) {
2090         $init->add_eval( $i );
2091     }
2092     if (@options) {
2093         return sub {
2094             my $objname;
2095             foreach $objname (@options) {
2096                 eval "save_object(\\$objname)";
2097             }
2098             output_all();
2099         }
2100     } else {
2101         return sub { save_main() };
2102     }
2103 }
2104
2105 1;
2106
2107 __END__
2108
2109 =head1 NAME
2110
2111 B::C - Perl compiler's C backend
2112
2113 =head1 SYNOPSIS
2114
2115         perl -MO=C[,OPTIONS] foo.pl
2116
2117 =head1 DESCRIPTION
2118
2119 This compiler backend takes Perl source and generates C source code
2120 corresponding to the internal structures that perl uses to run
2121 your program. When the generated C source is compiled and run, it
2122 cuts out the time which perl would have taken to load and parse
2123 your program into its internal semi-compiled form. That means that
2124 compiling with this backend will not help improve the runtime
2125 execution speed of your program but may improve the start-up time.
2126 Depending on the environment in which your program runs this may be
2127 either a help or a hindrance.
2128
2129 =head1 OPTIONS
2130
2131 If there are any non-option arguments, they are taken to be
2132 names of objects to be saved (probably doesn't work properly yet).
2133 Without extra arguments, it saves the main program.
2134
2135 =over 4
2136
2137 =item B<-ofilename>
2138
2139 Output to filename instead of STDOUT
2140
2141 =item B<-v>
2142
2143 Verbose compilation (currently gives a few compilation statistics).
2144
2145 =item B<-->
2146
2147 Force end of options
2148
2149 =item B<-uPackname>
2150
2151 Force apparently unused subs from package Packname to be compiled.
2152 This allows programs to use eval "foo()" even when sub foo is never
2153 seen to be used at compile time. The down side is that any subs which
2154 really are never used also have code generated. This option is
2155 necessary, for example, if you have a signal handler foo which you
2156 initialise with C<$SIG{BAR} = "foo">.  A better fix, though, is just
2157 to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
2158 options. The compiler tries to figure out which packages may possibly
2159 have subs in which need compiling but the current version doesn't do
2160 it very well. In particular, it is confused by nested packages (i.e.
2161 of the form C<A::B>) where package C<A> does not contain any subs.
2162
2163 =item B<-D>
2164
2165 Debug options (concatenated or separate flags like C<perl -D>).
2166
2167 =item B<-Do>
2168
2169 OPs, prints each OP as it's processed
2170
2171 =item B<-Dc>
2172
2173 COPs, prints COPs as processed (incl. file & line num)
2174
2175 =item B<-DA>
2176
2177 prints AV information on saving
2178
2179 =item B<-DC>
2180
2181 prints CV information on saving
2182
2183 =item B<-DM>
2184
2185 prints MAGIC information on saving
2186
2187 =item B<-f>
2188
2189 Force options/optimisations on or off one at a time. You can explicitly
2190 disable an option using B<-fno-option>. All options default to
2191 B<disabled>.
2192
2193 =over 4
2194
2195 =item B<-fcog>
2196
2197 Copy-on-grow: PVs declared and initialised statically.
2198
2199 =item B<-fsave-data>
2200
2201 Save package::DATA filehandles ( only available with PerlIO ).
2202
2203 =item B<-fppaddr>
2204
2205 Optimize the initialization of op_ppaddr.
2206
2207 =item B<-fwarn-sv>
2208
2209 Optimize the initialization of cop_warnings.
2210
2211 =item B<-fuse-script-name>
2212
2213 Use the script name instead of the program name as $0.
2214
2215 =item B<-fsave-sig-hash>
2216
2217 Save compile-time modifications to the %SIG hash.
2218
2219 =back
2220
2221 =item B<-On>
2222
2223 Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>.
2224
2225 =over 4
2226
2227 =item B<-O0>
2228
2229 Disable all optimizations.
2230
2231 =item B<-O1>
2232
2233 Enable B<-fcog>.
2234
2235 =item B<-O2>
2236
2237 Enable B<-fppaddr>, B<-fwarn-sv>.
2238
2239 =back
2240
2241 =item B<-llimit>
2242
2243 Some C compilers impose an arbitrary limit on the length of string
2244 constants (e.g. 2048 characters for Microsoft Visual C++).  The
2245 B<-llimit> options tells the C backend not to generate string literals
2246 exceeding that limit.
2247
2248 =back
2249
2250 =head1 EXAMPLES
2251
2252     perl -MO=C,-ofoo.c foo.pl
2253     perl cc_harness -o foo foo.c
2254
2255 Note that C<cc_harness> lives in the C<B> subdirectory of your perl
2256 library directory. The utility called C<perlcc> may also be used to
2257 help make use of this compiler.
2258
2259     perl -MO=C,-v,-DcA,-l2048 bar.pl > /dev/null
2260
2261 =head1 BUGS
2262
2263 Plenty. Current status: experimental.
2264
2265 =head1 AUTHOR
2266
2267 Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
2268
2269 =cut