906c1a4e9c95d3705390c24ff4be391fb30dd6c7
[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
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          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     $xpvavsect->add(sprintf("0, -1, -1, 0, 0.0, 0, Nullhv, 0, 0"));
1186     $svsect->add(sprintf("&xpvav_list[%d], %lu, 0x%x",
1187                          $xpvavsect->index, $av->REFCNT  , $av->FLAGS));
1188     my $sv_list_index = $svsect->index;
1189     my $fill = $av->FILL;
1190     $av->save_magic;
1191     warn sprintf("saving AV 0x%x FILL=$fill", $$av)
1192         if $debug_av;
1193     # XXX AVf_REAL is wrong test: need to save comppadlist but not stack
1194     #if ($fill > -1 && ($avflags & AVf_REAL)) {
1195     if ($fill > -1) {
1196         my @array = $av->ARRAY;
1197         if ($debug_av) {
1198             my $el;
1199             my $i = 0;
1200             foreach $el (@array) {
1201                 warn sprintf("AV 0x%x[%d] = %s 0x%x\n",
1202                              $$av, $i++, class($el), $$el);
1203             }
1204         }
1205 #       my @names = map($_->save, @array);
1206         # XXX Better ways to write loop?
1207         # Perhaps svp[0] = ...; svp[1] = ...; svp[2] = ...;
1208         # Perhaps I32 i = 0; svp[i++] = ...; svp[i++] = ...; svp[i++] = ...;
1209
1210         # micro optimization: op/pat.t ( and other code probably )
1211         # has very large pads ( 20k/30k elements ) passing them to
1212         # ->add is a performance bottleneck: passing them as a
1213         # single string cuts runtime from 6min20sec to 40sec
1214
1215         # you want to keep this out of the no_split/split
1216         # map("\t*svp++ = (SV*)$_;", @names),
1217         my $acc = '';
1218         foreach my $i ( 0..$#array ) {
1219               $acc .= "\t*svp++ = (SV*)" . $array[$i]->save . ";\n\t";
1220         }
1221         $acc .= "\n";
1222
1223         $init->no_split;
1224         $init->add("{",
1225                    "\tSV **svp;",
1226                    "\tAV *av = (AV*)&sv_list[$sv_list_index];",
1227                    "\tav_extend(av, $fill);",
1228                    "\tsvp = AvARRAY(av);" );
1229         $init->add($acc);
1230         $init->add("\tAvFILLp(av) = $fill;",
1231                    "}");
1232         $init->split;
1233         # we really added a lot of lines ( B::C::InitSection->add
1234         # should really scan for \n, but that would slow
1235         # it down
1236         $init->inc_count( $#array );
1237     } else {
1238         my $max = $av->MAX;
1239         $init->add("av_extend((AV*)&sv_list[$sv_list_index], $max);")
1240             if $max > -1;
1241     }
1242     return savesym($av, "(AV*)&sv_list[$sv_list_index]");
1243 }
1244
1245 sub B::HV::save {
1246     my ($hv) = @_;
1247     my $sym = objsym($hv);
1248     return $sym if defined $sym;
1249     my $name = $hv->NAME;
1250     if ($name) {
1251         # It's a stash
1252
1253         # A perl bug means HvPMROOT isn't altered when a PMOP is freed. Usually
1254         # the only symptom is that sv_reset tries to reset the PMf_USED flag of
1255         # a trashed op but we look at the trashed op_type and segfault.
1256         #my $adpmroot = ${$hv->PMROOT};
1257         my $adpmroot = 0;
1258         $decl->add("static HV *hv$hv_index;");
1259         # XXX Beware of weird package names containing double-quotes, \n, ...?
1260         $init->add(qq[hv$hv_index = gv_stashpv("$name", TRUE);]);
1261         if ($adpmroot) {
1262             $init->add(sprintf("HvPMROOT(hv$hv_index) = (PMOP*)s\\_%x;",
1263                                $adpmroot));
1264         }
1265         $sym = savesym($hv, "hv$hv_index");
1266         $hv_index++;
1267         return $sym;
1268     }
1269     # It's just an ordinary HV
1270     $xpvhvsect->add(sprintf("0, 0, %d, 0, 0.0, 0, Nullhv, %d, 0, 0, 0",
1271                             $hv->MAX, $hv->RITER));
1272     $svsect->add(sprintf("&xpvhv_list[%d], %lu, 0x%x",
1273                          $xpvhvsect->index, $hv->REFCNT  , $hv->FLAGS));
1274     my $sv_list_index = $svsect->index;
1275     my @contents = $hv->ARRAY;
1276     if (@contents) {
1277         my $i;
1278         for ($i = 1; $i < @contents; $i += 2) {
1279             $contents[$i] = $contents[$i]->save;
1280         }
1281         $init->no_split;
1282         $init->add("{", "\tHV *hv = (HV*)&sv_list[$sv_list_index];");
1283         while (@contents) {
1284             my ($key, $value) = splice(@contents, 0, 2);
1285             $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1286                                cstring($key),length(pack "a*",$key),
1287                                $value, hash($key)));
1288 #           $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1289 #                              cstring($key),length($key),$value, 0));
1290         }
1291         $init->add("}");
1292         $init->split;
1293     }
1294     $hv->save_magic();
1295     return savesym($hv, "(HV*)&sv_list[$sv_list_index]");
1296 }
1297
1298 sub B::IO::save_data {
1299     my( $io, $globname, @data ) = @_;
1300     my $data = join '', @data;
1301
1302     # XXX using $DATA might clobber it!
1303     my $sym = svref_2object( \\$data )->save;
1304     $init->add( split /\n/, <<CODE );
1305     {
1306         GV* gv = (GV*)gv_fetchpv( "$globname", TRUE, SVt_PV );
1307         SV* sv = $sym;
1308         GvSV( gv ) = sv;
1309     }
1310 CODE
1311     # for PerlIO::scalar
1312     $use_xsloader = 1;
1313     $init->add_eval( sprintf 'open(%s, "<", $%s)', $globname, $globname );
1314 }
1315
1316 sub B::IO::save {
1317     my ($io) = @_;
1318     my $sym = objsym($io);
1319     return $sym if defined $sym;
1320     my $pv = $io->PV;
1321     $pv = '' unless defined $pv;
1322     my $len = length($pv);
1323     $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",
1324                             $len, $len+1, $io->IVX, $io->NVX, $io->LINES,
1325                             $io->PAGE, $io->PAGE_LEN, $io->LINES_LEFT,
1326                             cstring($io->TOP_NAME), cstring($io->FMT_NAME), 
1327                             cstring($io->BOTTOM_NAME), $io->SUBPROCESS,
1328                             cchar($io->IoTYPE), $io->IoFLAGS));
1329     $svsect->add(sprintf("&xpvio_list[%d], %lu, 0x%x",
1330                          $xpviosect->index, $io->REFCNT , $io->FLAGS));
1331     $sym = savesym($io, sprintf("(IO*)&sv_list[%d]", $svsect->index));
1332     # deal with $x = *STDIN/STDOUT/STDERR{IO}
1333     my $perlio_func;
1334     foreach ( qw(stdin stdout stderr) ) {
1335         $io->IsSTD($_) and $perlio_func = $_;
1336     }
1337     if( $perlio_func ) {
1338         $init->add( "IoIFP(${sym})=PerlIO_${perlio_func}();" );
1339         $init->add( "IoOFP(${sym})=PerlIO_${perlio_func}();" );
1340     }
1341
1342     my ($field, $fsym);
1343     foreach $field (qw(TOP_GV FMT_GV BOTTOM_GV)) {
1344         $fsym = $io->$field();
1345         if ($$fsym) {
1346             $init->add(sprintf("Io$field($sym) = (GV*)s\\_%x;", $$fsym));
1347             $fsym->save;
1348         }
1349     }
1350     $io->save_magic;
1351     return $sym;
1352 }
1353
1354 sub B::SV::save {
1355     my $sv = shift;
1356     # This is where we catch an honest-to-goodness Nullsv (which gets
1357     # blessed into B::SV explicitly) and any stray erroneous SVs.
1358     return 0 unless $$sv;
1359     confess sprintf("cannot save that type of SV: %s (0x%x)\n",
1360                     class($sv), $$sv);
1361 }
1362
1363 sub output_all {
1364     my $init_name = shift;
1365     my $section;
1366     my @sections = ($opsect, $unopsect, $binopsect, $logopsect, $condopsect,
1367                     $listopsect, $pmopsect, $svopsect, $padopsect, $pvopsect,
1368                     $loopsect, $copsect, $svsect, $xpvsect,
1369                     $xpvavsect, $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect,
1370                     $xpvmgsect, $xpvlvsect, $xrvsect, $xpvbmsect, $xpviosect);
1371     $symsect->output(\*STDOUT, "#define %s\n");
1372     print "\n";
1373     output_declarations();
1374     foreach $section (@sections) {
1375         my $lines = $section->index + 1;
1376         if ($lines) {
1377             my $name = $section->name;
1378             my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
1379             print "Static $typename ${name}_list[$lines];\n";
1380         }
1381     }
1382     # XXX hack for when Perl accesses PVX of GVs
1383     print 'Static char emptystring[] = "\0";';
1384
1385     $decl->output(\*STDOUT, "%s\n");
1386     print "\n";
1387     foreach $section (@sections) {
1388         my $lines = $section->index + 1;
1389         if ($lines) {
1390             my $name = $section->name;
1391             my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
1392             printf "static %s %s_list[%u] = {\n", $typename, $name, $lines;
1393             $section->output(\*STDOUT, "\t{ %s }, /* %d */\n");
1394             print "};\n\n";
1395         }
1396     }
1397
1398     $init->output(\*STDOUT, "\t%s\n", $init_name );
1399     if ($verbose) {
1400         warn compile_stats();
1401         warn "NULLOP count: $nullop_count\n";
1402     }
1403 }
1404
1405 sub output_declarations {
1406     print <<'EOT';
1407 #ifdef BROKEN_STATIC_REDECL
1408 #define Static extern
1409 #else
1410 #define Static static
1411 #endif /* BROKEN_STATIC_REDECL */
1412
1413 #ifdef BROKEN_UNION_INIT
1414 /*
1415  * Cribbed from cv.h with ANY (a union) replaced by void*.
1416  * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
1417  */
1418 typedef struct {
1419     char *      xpv_pv;         /* pointer to malloced string */
1420     STRLEN      xpv_cur;        /* length of xp_pv as a C string */
1421     STRLEN      xpv_len;        /* allocated size */
1422     IV          xof_off;        /* integer value */
1423     NV          xnv_nv;         /* numeric value, if any */
1424     MAGIC*      xmg_magic;      /* magic for scalar array */
1425     HV*         xmg_stash;      /* class package */
1426
1427     HV *        xcv_stash;
1428     OP *        xcv_start;
1429     OP *        xcv_root;
1430     void      (*xcv_xsub) (pTHX_ CV*);
1431     ANY         xcv_xsubany;
1432     GV *        xcv_gv;
1433     char *      xcv_file;
1434     long        xcv_depth;      /* >= 2 indicates recursive call */
1435     AV *        xcv_padlist;
1436     CV *        xcv_outside;
1437 EOT
1438     print <<'EOT' if $] < 5.009;
1439 #ifdef USE_5005THREADS
1440     perl_mutex *xcv_mutexp;
1441     struct perl_thread *xcv_owner;      /* current owner thread */
1442 #endif /* USE_5005THREADS */
1443 EOT
1444     print <<'EOT';
1445     cv_flags_t  xcv_flags;
1446     U32         xcv_outside_seq; /* the COP sequence (at the point of our
1447                                   * compilation) in the lexically enclosing
1448                                   * sub */
1449 } XPVCV_or_similar;
1450 #define ANYINIT(i) i
1451 #else
1452 #define XPVCV_or_similar XPVCV
1453 #define ANYINIT(i) {i}
1454 #endif /* BROKEN_UNION_INIT */
1455 #define Nullany ANYINIT(0)
1456
1457 #define UNUSED 0
1458 #define sym_0 0
1459 EOT
1460     print "static GV *gv_list[$gv_index];\n" if $gv_index;
1461     print "\n";
1462 }
1463
1464
1465 sub output_boilerplate {
1466     print <<'EOT';
1467 #include "EXTERN.h"
1468 #include "perl.h"
1469 #include "XSUB.h"
1470
1471 /* Workaround for mapstart: the only op which needs a different ppaddr */
1472 #undef Perl_pp_mapstart
1473 #define Perl_pp_mapstart Perl_pp_grepstart
1474 #undef OP_MAPSTART
1475 #define OP_MAPSTART OP_GREPSTART
1476 #define XS_DynaLoader_boot_DynaLoader boot_DynaLoader
1477 EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
1478
1479 static void xs_init (pTHX);
1480 static void dl_init (pTHX);
1481 static PerlInterpreter *my_perl;
1482 EOT
1483 }
1484
1485 sub init_op_addr {
1486     my( $op_type, $num ) = @_;
1487     my $op_list = $op_type."_list";
1488
1489     $init->add( split /\n/, <<EOT );
1490     {
1491         int i;
1492
1493         for( i = 0; i < ${num}; ++i )
1494         {
1495             ${op_list}\[i].op_ppaddr = PL_ppaddr[INT2PTR(int,${op_list}\[i].op_ppaddr)];
1496         }
1497     }
1498 EOT
1499 }
1500
1501 sub init_op_warn {
1502     my( $op_type, $num ) = @_;
1503     my $op_list = $op_type."_list";
1504
1505     # for resons beyond imagination, MSVC5 considers pWARN_ALL non-const
1506     $init->add( split /\n/, <<EOT );
1507     {
1508         int i;
1509
1510         for( i = 0; i < ${num}; ++i )
1511         {
1512             switch( (int)(${op_list}\[i].cop_warnings) )
1513             {
1514             case 1:
1515                 ${op_list}\[i].cop_warnings = pWARN_ALL;
1516                 break;
1517             case 2:
1518                 ${op_list}\[i].cop_warnings = pWARN_NONE;
1519                 break;
1520             case 3:
1521                 ${op_list}\[i].cop_warnings = pWARN_STD;
1522                 break;
1523             default:
1524                 break;
1525             }
1526         }
1527     }
1528 EOT
1529 }
1530
1531 sub output_main {
1532     print <<'EOT';
1533 /* if USE_IMPLICIT_SYS, we need a 'real' exit */
1534 #if defined(exit)
1535 #undef exit
1536 #endif
1537
1538 int
1539 main(int argc, char **argv, char **env)
1540 {
1541     int exitstatus;
1542     int i;
1543     char **fakeargv;
1544     GV* tmpgv;
1545     SV* tmpsv;
1546     int options_count;
1547
1548     PERL_SYS_INIT3(&argc,&argv,&env);
1549
1550     if (!PL_do_undump) {
1551         my_perl = perl_alloc();
1552         if (!my_perl)
1553             exit(1);
1554         perl_construct( my_perl );
1555         PL_perl_destruct_level = 0;
1556     }
1557 EOT
1558     if( $ithreads ) {
1559         # XXX init free elems!
1560         my $pad_len = regex_padav->FILL + 1 - 1; # first is an avref
1561
1562         print <<EOT;
1563 #ifdef USE_ITHREADS
1564     for( i = 0; i < $pad_len; ++i ) {
1565         av_push( PL_regex_padav, newSViv(0) );
1566     }
1567     PL_regex_pad = AvARRAY( PL_regex_padav );
1568 #endif
1569 EOT
1570     }
1571
1572     print <<'EOT';
1573 #ifdef CSH
1574     if (!PL_cshlen) 
1575       PL_cshlen = strlen(PL_cshname);
1576 #endif
1577
1578 #ifdef ALLOW_PERL_OPTIONS
1579 #define EXTRA_OPTIONS 3
1580 #else
1581 #define EXTRA_OPTIONS 4
1582 #endif /* ALLOW_PERL_OPTIONS */
1583     New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
1584
1585     fakeargv[0] = argv[0];
1586     fakeargv[1] = "-e";
1587     fakeargv[2] = "";
1588     options_count = 3;
1589 EOT
1590     # honour -T
1591     print <<EOT;
1592     if( ${^TAINT} ) {
1593         fakeargv[options_count] = "-T";
1594         ++options_count;
1595     }
1596 EOT
1597     print <<'EOT';
1598 #ifndef ALLOW_PERL_OPTIONS
1599     fakeargv[options_count] = "--";
1600     ++options_count;
1601 #endif /* ALLOW_PERL_OPTIONS */
1602     for (i = 1; i < argc; i++)
1603         fakeargv[i + options_count - 1] = argv[i];
1604     fakeargv[argc + options_count - 1] = 0;
1605
1606     exitstatus = perl_parse(my_perl, xs_init, argc + options_count - 1,
1607                             fakeargv, NULL);
1608
1609     if (exitstatus)
1610         exit( exitstatus );
1611
1612     TAINT;
1613 EOT
1614
1615     if( $use_perl_script_name ) {
1616         my $dollar_0 = $0;
1617         $dollar_0 =~ s/\\/\\\\/g;
1618         $dollar_0 = '"' . $dollar_0 . '"';
1619
1620         print <<EOT;
1621     if ((tmpgv = gv_fetchpv("0",TRUE, SVt_PV))) {/* $0 */
1622         tmpsv = GvSV(tmpgv);
1623         sv_setpv(tmpsv, ${dollar_0});
1624         SvSETMAGIC(tmpsv);
1625     }
1626 EOT
1627     }
1628     else {
1629         print <<EOT;
1630     if ((tmpgv = gv_fetchpv("0",TRUE, SVt_PV))) {/* $0 */
1631         tmpsv = GvSV(tmpgv);
1632         sv_setpv(tmpsv, argv[0]);
1633         SvSETMAGIC(tmpsv);
1634     }
1635 EOT
1636     }
1637
1638     print <<'EOT';
1639     if ((tmpgv = gv_fetchpv("\030",TRUE, SVt_PV))) {/* $^X */
1640         tmpsv = GvSV(tmpgv);
1641 #ifdef WIN32
1642         sv_setpv(tmpsv,"perl.exe");
1643 #else
1644         sv_setpv(tmpsv,"perl");
1645 #endif
1646         SvSETMAGIC(tmpsv);
1647     }
1648
1649     TAINT_NOT;
1650
1651     /* PL_main_cv = PL_compcv; */
1652     PL_compcv = 0;
1653
1654     exitstatus = perl_init();
1655     if (exitstatus)
1656         exit( exitstatus );
1657     dl_init(aTHX);
1658
1659     exitstatus = perl_run( my_perl );
1660
1661     perl_destruct( my_perl );
1662     perl_free( my_perl );
1663
1664     PERL_SYS_TERM();
1665
1666     exit( exitstatus );
1667 }
1668
1669 /* yanked from perl.c */
1670 static void
1671 xs_init(pTHX)
1672 {
1673     char *file = __FILE__;
1674     dTARG;
1675     dSP;
1676 EOT
1677     print "\n#ifdef USE_DYNAMIC_LOADING";
1678     print qq/\n\tnewXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);/;
1679     print "\n#endif\n" ;
1680     # delete $xsub{'DynaLoader'}; 
1681     delete $xsub{'UNIVERSAL'}; 
1682     print("/* bootstrapping code*/\n\tSAVETMPS;\n");
1683     print("\ttarg=sv_newmortal();\n");
1684     print "#ifdef USE_DYNAMIC_LOADING\n";
1685     print "\tPUSHMARK(sp);\n";
1686     print qq/\tXPUSHp("DynaLoader",strlen("DynaLoader"));\n/;
1687     print qq/\tPUTBACK;\n/;
1688     print "\tboot_DynaLoader(aTHX_ NULL);\n";
1689     print qq/\tSPAGAIN;\n/;
1690     print "#endif\n";
1691     foreach my $stashname (keys %xsub){
1692         if ($xsub{$stashname} !~ m/Dynamic/ ) {
1693            my $stashxsub=$stashname;
1694            $stashxsub  =~ s/::/__/g; 
1695            print "\tPUSHMARK(sp);\n";
1696            print qq/\tXPUSHp("$stashname",strlen("$stashname"));\n/;
1697            print qq/\tPUTBACK;\n/;
1698            print "\tboot_$stashxsub(aTHX_ NULL);\n";
1699            print qq/\tSPAGAIN;\n/;
1700         }   
1701     }
1702     print("\tFREETMPS;\n/* end bootstrapping code */\n");
1703     print "}\n";
1704     
1705 print <<'EOT';
1706 static void
1707 dl_init(pTHX)
1708 {
1709     char *file = __FILE__;
1710     dTARG;
1711     dSP;
1712 EOT
1713     print("/* Dynamicboot strapping code*/\n\tSAVETMPS;\n");
1714     print("\ttarg=sv_newmortal();\n");
1715     foreach my $stashname (@DynaLoader::dl_modules) {
1716         warn "Loaded $stashname\n";
1717         if (exists($xsub{$stashname}) && $xsub{$stashname} =~ m/Dynamic/) {
1718            my $stashxsub=$stashname;
1719            $stashxsub  =~ s/::/__/g; 
1720            print "\tPUSHMARK(sp);\n";
1721            print qq/\tXPUSHp("$stashname",/,length($stashname),qq/);\n/;
1722            print qq/\tPUTBACK;\n/;
1723            print "#ifdef USE_DYNAMIC_LOADING\n";
1724            warn "bootstrapping $stashname added to xs_init\n";
1725            if( $xsub{$stashname} eq 'Dynamic' ) {
1726               print qq/\tperl_call_method("bootstrap",G_DISCARD);\n/;
1727            }
1728            else {
1729               print qq/\tperl_call_pv("XSLoader::load",G_DISCARD);\n/;
1730            }
1731            print "#else\n";
1732            print "\tboot_$stashxsub(aTHX_ NULL);\n";
1733            print "#endif\n";
1734            print qq/\tSPAGAIN;\n/;
1735         }   
1736     }
1737     print("\tFREETMPS;\n/* end Dynamic bootstrapping code */\n");
1738     print "}\n";
1739 }
1740 sub dump_symtable {
1741     # For debugging
1742     my ($sym, $val);
1743     warn "----Symbol table:\n";
1744     while (($sym, $val) = each %symtable) {
1745         warn "$sym => $val\n";
1746     }
1747     warn "---End of symbol table\n";
1748 }
1749
1750 sub save_object {
1751     my $sv;
1752     foreach $sv (@_) {
1753         svref_2object($sv)->save;
1754     }
1755 }       
1756
1757 sub Dummy_BootStrap { }            
1758
1759 sub B::GV::savecv 
1760 {
1761  my $gv = shift;
1762  my $package=$gv->STASH->NAME;
1763  my $name = $gv->NAME;
1764  my $cv = $gv->CV;
1765  my $sv = $gv->SV;
1766  my $av = $gv->AV;
1767  my $hv = $gv->HV;
1768
1769  my $fullname = $gv->STASH->NAME . "::" . $gv->NAME;
1770
1771  # We may be looking at this package just because it is a branch in the 
1772  # symbol table which is on the path to a package which we need to save
1773  # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
1774  # 
1775  return unless ($unused_sub_packages{$package});
1776  return unless ($$cv || $$av || $$sv || $$hv);
1777  $gv->save;
1778 }
1779
1780 sub mark_package
1781 {    
1782  my $package = shift;
1783  unless ($unused_sub_packages{$package})
1784   {    
1785    no strict 'refs';
1786    $unused_sub_packages{$package} = 1;
1787    if (defined @{$package.'::ISA'})
1788     {
1789      foreach my $isa (@{$package.'::ISA'}) 
1790       {
1791        if ($isa eq 'DynaLoader')
1792         {
1793          unless (defined(&{$package.'::bootstrap'}))
1794           {                    
1795            warn "Forcing bootstrap of $package\n";
1796            eval { $package->bootstrap }; 
1797           }
1798         }
1799 #      else
1800         {
1801          unless ($unused_sub_packages{$isa})
1802           {
1803            warn "$isa saved (it is in $package\'s \@ISA)\n";
1804            mark_package($isa);
1805           }
1806         }
1807       }
1808     }
1809   }
1810  return 1;
1811 }
1812      
1813 sub should_save
1814 {
1815  no strict qw(vars refs);
1816  my $package = shift;
1817  $package =~ s/::$//;
1818  return $unused_sub_packages{$package} = 0 if ($package =~ /::::/);  # skip ::::ISA::CACHE etc.
1819  # warn "Considering $package\n";#debug
1820  foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages)) 
1821   {  
1822    # If this package is a prefix to something we are saving, traverse it 
1823    # but do not mark it for saving if it is not already
1824    # e.g. to get to Getopt::Long we need to traverse Getopt but need
1825    # not save Getopt
1826    return 1 if ($u =~ /^$package\:\:/);
1827   }
1828  if (exists $unused_sub_packages{$package})
1829   {
1830    # warn "Cached $package is ".$unused_sub_packages{$package}."\n"; 
1831    delete_unsaved_hashINC($package) unless  $unused_sub_packages{$package} ;
1832    return $unused_sub_packages{$package}; 
1833   }
1834  # Omit the packages which we use (and which cause grief
1835  # because of fancy "goto &$AUTOLOAD" stuff).
1836  # XXX Surely there must be a nicer way to do this.
1837  if ($package eq "FileHandle" || $package eq "Config" || 
1838      $package eq "SelectSaver" || $package =~/^(B|IO)::/) 
1839   {
1840    delete_unsaved_hashINC($package);
1841    return $unused_sub_packages{$package} = 0;
1842   }
1843  # Now see if current package looks like an OO class this is probably too strong.
1844  foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE)) 
1845   {
1846    if (UNIVERSAL::can($package, $m))
1847     {
1848      warn "$package has method $m: saving package\n";#debug
1849      return mark_package($package);
1850     }
1851   }
1852  delete_unsaved_hashINC($package);
1853  return $unused_sub_packages{$package} = 0;
1854 }
1855 sub delete_unsaved_hashINC{
1856         my $packname=shift;
1857         $packname =~ s/\:\:/\//g;
1858         $packname .= '.pm';
1859 #       warn "deleting $packname" if $INC{$packname} ;# debug
1860         delete $INC{$packname};
1861 }
1862 sub walkpackages 
1863 {
1864  my ($symref, $recurse, $prefix) = @_;
1865  my $sym;
1866  my $ref;
1867  no strict 'vars';
1868  $prefix = '' unless defined $prefix;
1869  while (($sym, $ref) = each %$symref) 
1870   {             
1871    local(*glob);
1872    *glob = $ref;
1873    if ($sym =~ /::$/) 
1874     {
1875      $sym = $prefix . $sym;
1876      if ($sym ne "main::" && $sym ne "<none>::" && &$recurse($sym)) 
1877       {
1878        walkpackages(\%glob, $recurse, $sym);
1879       }
1880     } 
1881   }
1882 }
1883
1884
1885 sub save_unused_subs 
1886 {
1887  no strict qw(refs);
1888  &descend_marked_unused;
1889  warn "Prescan\n";
1890  walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
1891  warn "Saving methods\n";
1892  walksymtable(\%{"main::"}, "savecv", \&should_save);
1893 }
1894
1895 sub save_context
1896 {
1897  my $curpad_nam = (comppadlist->ARRAY)[0]->save;
1898  my $curpad_sym = (comppadlist->ARRAY)[1]->save;
1899  my $inc_hv     = svref_2object(\%INC)->save;
1900  my $inc_av     = svref_2object(\@INC)->save;
1901  my $amagic_generate= amagic_generation;          
1902  $init->add(   "PL_curpad = AvARRAY($curpad_sym);",
1903                "GvHV(PL_incgv) = $inc_hv;",
1904                "GvAV(PL_incgv) = $inc_av;",
1905                "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
1906                "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
1907                 "PL_amagic_generation= $amagic_generate;" );
1908 }
1909
1910 sub descend_marked_unused {
1911     foreach my $pack (keys %unused_sub_packages)
1912     {
1913         mark_package($pack);
1914     }
1915 }
1916  
1917 sub save_main {
1918     # this is mainly for the test suite
1919     my $warner = $SIG{__WARN__};
1920     local $SIG{__WARN__} = sub { print STDERR @_ };
1921
1922     warn "Starting compile\n";
1923     warn "Walking tree\n";
1924     seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
1925     walkoptree(main_root, "save");
1926     warn "done main optree, walking symtable for extras\n" if $debug_cv;
1927     save_unused_subs();
1928     # XSLoader was used, force saving of XSLoader::load
1929     if( $use_xsloader ) {
1930         my $cv = svref_2object( \&XSLoader::load );
1931         $cv->save;
1932     }
1933     # save %SIG ( in case it was set in a BEGIN block )
1934     if( $save_sig ) {
1935         local $SIG{__WARN__} = $warner;
1936         $init->no_split;
1937         $init->add("{", "\tHV* hv = get_hv(\"main::SIG\",1);" );
1938         foreach my $k ( keys %SIG ) {
1939             next unless ref $SIG{$k};
1940             my $cv = svref_2object( \$SIG{$k} );
1941             my $sv = $cv->save;
1942             $init->add('{',sprintf 'SV* sv = (SV*)%s;', $sv );
1943             $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
1944                                cstring($k),length(pack "a*",$k),
1945                                'sv', hash($k)));
1946             $init->add('mg_set(sv);','}');
1947         }
1948         $init->add('}');
1949         $init->split;
1950     }
1951     # honour -w
1952     $init->add( sprintf "    PL_dowarn = ( %s ) ? G_WARN_ON : G_WARN_OFF;", $^W );
1953     #
1954     my $init_av = init_av->save;
1955     my $end_av = end_av->save;
1956     $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1957                sprintf("PL_main_start = s\\_%x;", ${main_start()}),
1958               "PL_initav = (AV *) $init_av;",
1959               "PL_endav = (AV*) $end_av;");
1960     save_context();
1961     # init op addrs ( must be the last action, otherwise
1962     # some ops might not be initialized
1963     if( $optimize_ppaddr ) {
1964         foreach my $i ( @op_sections ) {
1965             my $section = $$i;
1966             next unless $section->index >= 0;
1967             init_op_addr( $section->name, $section->index + 1);
1968         }
1969     }
1970     init_op_warn( $copsect->name, $copsect->index + 1)
1971       if $optimize_warn_sv && $copsect->index >= 0;
1972
1973     warn "Writing output\n";
1974     output_boilerplate();
1975     print "\n";
1976     output_all("perl_init");
1977     print "\n";
1978     output_main();
1979 }
1980
1981 sub init_sections {
1982     my @sections = (decl => \$decl, sym => \$symsect,
1983                     binop => \$binopsect, condop => \$condopsect,
1984                     cop => \$copsect, padop => \$padopsect,
1985                     listop => \$listopsect, logop => \$logopsect,
1986                     loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
1987                     pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
1988                     sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
1989                     xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
1990                     xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
1991                     xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
1992                     xrv => \$xrvsect, xpvbm => \$xpvbmsect,
1993                     xpvio => \$xpviosect);
1994     my ($name, $sectref);
1995     while (($name, $sectref) = splice(@sections, 0, 2)) {
1996         $$sectref = new B::C::Section $name, \%symtable, 0;
1997     }
1998     $init = new B::C::InitSection 'init', \%symtable, 0;
1999 }
2000
2001 sub mark_unused
2002 {
2003  my ($arg,$val) = @_;
2004  $unused_sub_packages{$arg} = $val;
2005 }
2006
2007 sub compile {
2008     my @options = @_;
2009     my ($option, $opt, $arg);
2010     my @eval_at_startup;
2011     my %option_map = ( 'cog' => \$pv_copy_on_grow,
2012                        'save-data' => \$save_data_fh,
2013                        'ppaddr' => \$optimize_ppaddr,
2014                        'warn-sv' => \$optimize_warn_sv,
2015                        'use-script-name' => \$use_perl_script_name,
2016                        'save-sig-hash' => \$save_sig,
2017                      );
2018     my %optimization_map = ( 0 => [ qw() ], # special case
2019                              1 => [ qw(-fcog) ],
2020                              2 => [ qw(-fwarn-sv -fppaddr) ],
2021                            );
2022   OPTION:
2023     while ($option = shift @options) {
2024         if ($option =~ /^-(.)(.*)/) {
2025             $opt = $1;
2026             $arg = $2;
2027         } else {
2028             unshift @options, $option;
2029             last OPTION;
2030         }
2031         if ($opt eq "-" && $arg eq "-") {
2032             shift @options;
2033             last OPTION;
2034         }
2035         if ($opt eq "w") {
2036             $warn_undefined_syms = 1;
2037         } elsif ($opt eq "D") {
2038             $arg ||= shift @options;
2039             foreach $arg (split(//, $arg)) {
2040                 if ($arg eq "o") {
2041                     B->debug(1);
2042                 } elsif ($arg eq "c") {
2043                     $debug_cops = 1;
2044                 } elsif ($arg eq "A") {
2045                     $debug_av = 1;
2046                 } elsif ($arg eq "C") {
2047                     $debug_cv = 1;
2048                 } elsif ($arg eq "M") {
2049                     $debug_mg = 1;
2050                 } else {
2051                     warn "ignoring unknown debug option: $arg\n";
2052                 }
2053             }
2054         } elsif ($opt eq "o") {
2055             $arg ||= shift @options;
2056             open(STDOUT, ">$arg") or return "$arg: $!\n";
2057         } elsif ($opt eq "v") {
2058             $verbose = 1;
2059         } elsif ($opt eq "u") {
2060             $arg ||= shift @options;
2061             mark_unused($arg,undef);
2062         } elsif ($opt eq "f") {
2063             $arg ||= shift @options;
2064             $arg =~ m/(no-)?(.*)/;
2065             my $no = defined($1) && $1 eq 'no-';
2066             $arg = $no ? $2 : $arg;
2067             if( exists $option_map{$arg} ) {
2068                 ${$option_map{$arg}} = !$no;
2069             } else {
2070                 die "Invalid optimization '$arg'";
2071             }
2072         } elsif ($opt eq "O") {
2073             $arg = 1 if $arg eq "";
2074             my @opt;
2075             foreach my $i ( 1 .. $arg ) {
2076                 push @opt, @{$optimization_map{$i}}
2077                     if exists $optimization_map{$i};
2078             }
2079             unshift @options, @opt;
2080         } elsif ($opt eq "e") {
2081             push @eval_at_startup, $arg;
2082         } elsif ($opt eq "l") {
2083             $max_string_len = $arg;
2084         }
2085     }
2086     init_sections();
2087     foreach my $i ( @eval_at_startup ) {
2088         $init->add_eval( $i );
2089     }
2090     if (@options) {
2091         return sub {
2092             my $objname;
2093             foreach $objname (@options) {
2094                 eval "save_object(\\$objname)";
2095             }
2096             output_all();
2097         }
2098     } else {
2099         return sub { save_main() };
2100     }
2101 }
2102
2103 1;
2104
2105 __END__
2106
2107 =head1 NAME
2108
2109 B::C - Perl compiler's C backend
2110
2111 =head1 SYNOPSIS
2112
2113         perl -MO=C[,OPTIONS] foo.pl
2114
2115 =head1 DESCRIPTION
2116
2117 This compiler backend takes Perl source and generates C source code
2118 corresponding to the internal structures that perl uses to run
2119 your program. When the generated C source is compiled and run, it
2120 cuts out the time which perl would have taken to load and parse
2121 your program into its internal semi-compiled form. That means that
2122 compiling with this backend will not help improve the runtime
2123 execution speed of your program but may improve the start-up time.
2124 Depending on the environment in which your program runs this may be
2125 either a help or a hindrance.
2126
2127 =head1 OPTIONS
2128
2129 If there are any non-option arguments, they are taken to be
2130 names of objects to be saved (probably doesn't work properly yet).
2131 Without extra arguments, it saves the main program.
2132
2133 =over 4
2134
2135 =item B<-ofilename>
2136
2137 Output to filename instead of STDOUT
2138
2139 =item B<-v>
2140
2141 Verbose compilation (currently gives a few compilation statistics).
2142
2143 =item B<-->
2144
2145 Force end of options
2146
2147 =item B<-uPackname>
2148
2149 Force apparently unused subs from package Packname to be compiled.
2150 This allows programs to use eval "foo()" even when sub foo is never
2151 seen to be used at compile time. The down side is that any subs which
2152 really are never used also have code generated. This option is
2153 necessary, for example, if you have a signal handler foo which you
2154 initialise with C<$SIG{BAR} = "foo">.  A better fix, though, is just
2155 to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
2156 options. The compiler tries to figure out which packages may possibly
2157 have subs in which need compiling but the current version doesn't do
2158 it very well. In particular, it is confused by nested packages (i.e.
2159 of the form C<A::B>) where package C<A> does not contain any subs.
2160
2161 =item B<-D>
2162
2163 Debug options (concatenated or separate flags like C<perl -D>).
2164
2165 =item B<-Do>
2166
2167 OPs, prints each OP as it's processed
2168
2169 =item B<-Dc>
2170
2171 COPs, prints COPs as processed (incl. file & line num)
2172
2173 =item B<-DA>
2174
2175 prints AV information on saving
2176
2177 =item B<-DC>
2178
2179 prints CV information on saving
2180
2181 =item B<-DM>
2182
2183 prints MAGIC information on saving
2184
2185 =item B<-f>
2186
2187 Force options/optimisations on or off one at a time. You can explicitly
2188 disable an option using B<-fno-option>. All options default to
2189 B<disabled>.
2190
2191 =over 4
2192
2193 =item B<-fcog>
2194
2195 Copy-on-grow: PVs declared and initialised statically.
2196
2197 =item B<-fsave-data>
2198
2199 Save package::DATA filehandles ( only available with PerlIO ).
2200
2201 =item B<-fppaddr>
2202
2203 Optimize the initialization of op_ppaddr.
2204
2205 =item B<-fwarn-sv>
2206
2207 Optimize the initialization of cop_warnings.
2208
2209 =item B<-fuse-script-name>
2210
2211 Use the script name instead of the program name as $0.
2212
2213 =item B<-fsave-sig-hash>
2214
2215 Save compile-time modifications to the %SIG hash.
2216
2217 =back
2218
2219 =item B<-On>
2220
2221 Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>.
2222
2223 =over 4
2224
2225 =item B<-O0>
2226
2227 Disable all optimizations.
2228
2229 =item B<-O1>
2230
2231 Enable B<-fcog>.
2232
2233 =item B<-O2>
2234
2235 Enable B<-fppaddr>, B<-fwarn-sv>.
2236
2237 =back
2238
2239 =item B<-llimit>
2240
2241 Some C compilers impose an arbitrary limit on the length of string
2242 constants (e.g. 2048 characters for Microsoft Visual C++).  The
2243 B<-llimit> options tells the C backend not to generate string literals
2244 exceeding that limit.
2245
2246 =back
2247
2248 =head1 EXAMPLES
2249
2250     perl -MO=C,-ofoo.c foo.pl
2251     perl cc_harness -o foo foo.c
2252
2253 Note that C<cc_harness> lives in the C<B> subdirectory of your perl
2254 library directory. The utility called C<perlcc> may also be used to
2255 help make use of this compiler.
2256
2257     perl -MO=C,-v,-DcA,-l2048 bar.pl > /dev/null
2258
2259 =head1 BUGS
2260
2261 Plenty. Current status: experimental.
2262
2263 =head1 AUTHOR
2264
2265 Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
2266
2267 =cut