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