Viewing File: /usr/local/cpanel/3rdparty/perl/536/cpanel-lib/x86_64-linux/B/C/Section.pm
package B::C::Section;
use B::C::Std;
# use warnings
use B qw/SVf_FAKE/;
use B::C::Helpers::Symtable ();
my %sections;
sub BOOTSTRAP_marker {
return q{BOOTSTRAP_XS_};
}
sub new ( $class, $section, $symtable, $default ) {
my $self = bless {
'name' => $section,
'symtable' => $symtable,
'default' => $default,
'values' => [],
'c_header' => [],
}, $class;
$sections{$section} = $self;
# if sv add a dummy sv_arenaroot to support global destruction
if ( $section eq 'sv' ) {
$self->add( "NULL, 0, SVTYPEMASK|" . SVf_FAKE . ", {0}" );
$self->debug("PL_sv_arenaroot");
}
return $self;
}
sub has_values ($self) {
return scalar @{ $self->{values} } >= 1 ? 1 : 0;
}
sub add ( $self, @list ) {
my $add_stack = 'B::C::Save'->can('_caller_comment');
if ( $list[-1] && ref $add_stack ) {
my $add = $add_stack->();
$list[-1] .= qq{\n} . $add if length $add;
}
push( @{ $self->{'values'} }, @list );
# return its position in the list (first one will be 0), avoid to call index just after in most cases
return $self->index();
}
sub reserve ( $self, $sv, $type = undef ) {
$sv or die("Need a symbol");
my $type_cast = $type ? "($type)" : '';
my $caller_package = ( caller(0) )[0];
$caller_package =~ s/^B:://;
my $ix = $self->add("FAKE $caller_package");
my $list_name = $self->{'name'} or die;
# (OP*)&svop_list[5]"
my $sym = sprintf( '%s&%s_list[%d]', $type_cast, $list_name, $ix );
B::C::Helpers::Symtable::savesym( $sv, $sym );
return ( $ix, $sym );
}
sub _convert_list_to_sprintf (@list) {
my @patterns;
my @args;
die "saddl should be called with an even number of arguments" unless scalar @list % 2 == 0;
while ( my ( $k, $v ) = splice( @list, 0, 2 ) ) {
push @patterns, $k;
if ( ref $v eq 'ARRAY' ) {
push @args, @$v;
}
else {
push @args, $v;
}
}
my $pattern = join( ', ', @patterns );
return sprintf( $pattern, @args );
}
sub sort ($self) { # used by shared_HE
my %line_to_int;
foreach my $l ( @{ $self->{'values'} } ) {
my $v = $l =~ qr{([0-9]+)} ? $1 : 0;
$line_to_int{$l} = $v;
}
my @sorted = sort { $line_to_int{$a} <=> $line_to_int{$b} } @{ $self->{'values'} };
$self->{'values'} = \@sorted;
return;
}
# simple add using sprintf: avoid boilerplates
# ex: sadd( "%d, %s", 1234, q{abcd} )
sub sadd ( $self, $pattern, @args ) {
return $self->add( sprintf( $pattern, @args ) );
}
# simple add using sprintf using input formatted as a list
# ex: saddl( "%d" => 1234, "%s" => q{abcd} )
sub saddl ( $self, @list ) {
return $self->add( _convert_list_to_sprintf(@list) );
}
# simple update using sprintf: avoid boilerplates
# ex: supdate( 1, "%d, %s", 1234, q{str} )
sub supdate ( $self, $row, $pattern, @args ) {
return $self->update( $row, sprintf( $pattern, @args ) );
}
# simple update using sprintf using input formatted as a list
# ex: supdatel( 1, "%d" => 1234, "%s" => q{str} )
sub supdatel ( $self, $row, @list ) {
return $self->update( $row, _convert_list_to_sprintf(@list) );
}
sub update ( $self, $row, $value ) {
die "Element does not exists" if $row > $self->index;
$self->{'values'}->[$row] = $value;
return;
}
sub supdate_field ( $self, $row, $field, $pattern, @args ) {
return $self->update_field( $row, $field, sprintf( $pattern, @args ) );
}
=pod
update_field: update a single value from an existing line
=cut
sub update_field ( $self, $row, $field, $value ) {
die "Need to call with row, field, value" unless defined $value;
my $line = $self->get($row);
my @fields = _field_split($line); # does not handle comma in comments
die "Invalid field id $field" if $field > $#fields;
$fields[$field] = $value;
$line = join ',', @fields; # update line
return $self->update( $row, $line );
}
sub _field_split ($to_split) {
my @list = split( ',', $to_split );
my @ok;
my ( $count_open, $count_close );
my $str;
my $reset = sub { $str = '', $count_open = $count_close = 0 };
$reset->();
foreach my $next (@list) {
$str .= ',' if length $str;
$str .= $next;
my $snext = $next;
$snext =~ s{"[^"]+"}{""}g; # remove weird content inside double quotes
$count_open += $snext =~ tr/(//;
$count_close += $snext =~ tr/)//;
#warn "$count_open vs $count_close: $str";
if ( $count_close == $count_open ) {
push @ok, $str;
$reset->();
}
}
die "Cannot split correctly '$to_split' (some leftover='$str')" if length $str;
return @ok;
}
sub get ( $self, $row = undef ) {
$row = $self->index if !defined $row; # get the last entry if not set
return $self->{'values'}->[$row];
}
sub get_bootstrapsub_rows ($self) {
my $bs_rows = {};
my $ix = -1;
foreach my $v ( @{ $self->{'values'} } ) {
++$ix;
if ( $v =~ qr{BOOTSTRAP_XS_\Q[[\E(.+?)\Q]]\E_XS_BOOTSTRAP} ) {
my $bs = $1;
$bs_rows->{$bs} //= [];
push @{ $bs_rows->{$bs} }, $ix;
}
}
return $bs_rows;
}
sub get_field ( $self, $row, $field ) {
die "Need to call with row, field" unless defined $field;
my $line = $self->get($row);
my @fields = _field_split($line); # does not handle comma in comments
die "Invalid field id $field" if $field > $#fields;
return $fields[$field];
}
sub get_fields ( $self, $row = undef ) {
my $line = $self->get($row);
return split( qr/\s*,\s*/, $line );
}
sub remove ($self) { # should be rename pop or remove last
return pop @{ $self->{'values'} };
}
sub name ($self) {
return $self->{'name'};
}
sub symtable ($self) {
return $self->{'symtable'};
}
sub default ($self) {
return $self->{'default'};
}
sub index ($self) {
return scalar( @{ $self->{'values'} } ) - 1;
}
sub typename ($self) {
my $name = $self->name;
my $typename = uc($name);
$typename = 'UNOP_AUX' if $typename eq 'UNOPAUX';
$typename = 'MyPADNAME' if $typename eq 'PADNAME';
$typename = 'SHARED_HE' if $typename eq 'SHAREDHE';
$typename = 'STATIC_MEMORY_AREA' if $typename eq 'MALLOC';
return $typename;
}
sub comment_for_op ( $self, @comments ) {
return $self->comment( B::OP::basop_comment(), ', ', @comments );
}
sub comment ( $self, @comments ) {
@comments = grep { defined $_ } @comments;
$self->{'comment'} = join( "", @comments ) if @comments;
return $self->{'comment'};
}
# add debugging info - stringified flags on -DF
my $debug_flags;
sub add_extra_comments {
return 1; # always on for now
# maybe use another standard flag ? - debug('flags')
#return $ENV{BC_DEVELOPING};
}
sub debug ( $self, @what ) {
# disable the sub when unused
if ( !$self->add_extra_comments ) {
# Scoped no warnings without loading the module.
local $^W;
BEGIN { ${^WARNING_BITS} = 0; }
*debug = sub { };
return;
}
# build our debug line for the current index
my $str;
my $dbg = scalar @what ? '' : 'undef';
foreach my $e (@what) {
do { $str = 'undef'; next } unless defined $e;
$str = ref($e) || $e;
}
continue {
$dbg .= ', ' if length $dbg;
$dbg .= $str;
}
my $ix = $self->index;
if ( defined $self->{'dbg'}->[$ix] ) {
$self->{'dbg'}->[$ix] .= ', ' . $dbg;
}
else {
$self->{'dbg'}->[$ix] = $dbg;
}
return $self->{'dbg'}->[$ix];
}
sub add_c_header ( $self, @headers ) {
push @{ $self->{'c_header'} }, @headers;
return;
}
sub output ( $self, $format ) {
# weird things would occur if we call the output more than once
die ref($self) . " output should only be called once" if $self->{_output_called};
$self->{_output_called} = 1;
my $sym = $self->symtable; # This should always be defined. see new
my $default = $self->default;
my $i = 0;
if ( $self->name eq 'sv' ) { # fixup arenaroot refcnt
my $len = scalar @{ $self->{'values'} };
$self->{'values'}->[0] =~ s/^NULL, 0/NULL, $len/;
}
my $comment = $self->comment;
my $output = '';
# check if the format already provide a closing comment
my $wrap_debug_with_comment = $format =~ qr{\Q*/\E\s+$} ? 0 : 1;
foreach my $i ( @{ $self->{'c_header'} } ) {
$output .= " $i\n";
}
foreach ( @{ $self->{'values'} } ) {
my $val = $_; # Copy so we don't overwrite on successive calls.
my $dbg = "";
my $ref = "";
if ( $self->add_extra_comments() && defined $comment && $i % 10 == 0 ) {
# every 10 lines add the comment header so we can easily read it
$output .= qq{\n} if $i;
$output .= qq{\t/* } . $comment . qq{ */\n\n};
}
$val =~ s{(s\\_[0-9a-f]+)}{ exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
if ( defined $self->{'dbg'}->[$i] ) {
$dbg = $self->{'dbg'}->[$i] . " " . $ref;
if ($wrap_debug_with_comment) {
$dbg = " /* " . $dbg . " */";
}
else {
$dbg = '- ' . $dbg;
}
}
$val =~ s{BOOTSTRAP_XS_\Q[[\E.+?\Q]]\E_XS_BOOTSTRAP}{0};
{
# Scoped no warnings without loading the module.
local $^W;
BEGIN { ${^WARNING_BITS} = 0; }
$output .= sprintf( $format, $val, $self->name, $i, $ref, $dbg );
}
++$i;
}
return $output;
}
1;
Back to Directory
File Manager