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