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