App-sh2p
view release on metacpan or search on metacpan
lib/App/sh2p/Handlers.pm view on Meta::CPAN
}
elsif ( $idx =~ /^\D+$/) { # \D is non-digit
# Process the lhs
my @tokens = App::sh2p::Parser::tokenise ($idx);
my @types = App::sh2p::Parser::identify (1, @tokens);
iout "\$$arr\[";
App::sh2p::Parser::convert (@tokens, @types);
out "] = ";
}
else {
if ( $idx =~ /^\s*\$/ ) {
define_idx_var ($idx);
}
iout "\$$arr\[$idx\] = ";
}
if ( !defined $rhs ) {
out 'undef'
}
else {
# Process the rhs
my @tokens = App::sh2p::Parser::tokenise ($rhs);
my @types = App::sh2p::Parser::identify (1, @tokens);
# Avoid recursion
die "++++ Internal error: Nested array assignment $in" if $types[0] eq 'ARRAY_ASSIGNMENT';
#print_types_tokens (\@types, \@tokens);
App::sh2p::Parser::convert (@tokens, @types);
}
out ";\n";
return $ntok;
}
############################################################################
sub Handle_break {
# Maybe check to see if we are in a heredoc?
# 0.05
#if (!App::sh2p::Utils::new_line()) {
# out "\n";
#}
return 1;
}
############################################################################
sub Handle_open_redirection {
my ($type, $filename) = @_;
#print STDERR "Handle_open_redirection: <$type> <$filename>\n";
my @caller = caller();
#print STDERR "Handle_open_redirection: @caller\n";
out ("\n");
my $var = 'sh2p_handle';
if (Register_variable($var, '$')) {
rd_iout "my \$$var;\n";
}
rd_iout ("open(\$$var,'$type',\"$filename\") or\n");
rd_iout (" die \"Unable to open $filename: \$!\";\n");
if ( $type eq '>' || $type eq '>>' ) {
$g_redirect_filename_w = $filename;
}
else {
$g_redirect_filename_r = $filename;
}
}
############################################################################
sub Handle_close_redirection {
my ($mode) = @_;
my $filename;
if ($mode eq 'w') {
$filename = $g_redirect_filename_w;
$g_redirect_filename_w = undef;
}
else {
$filename = $g_redirect_filename_r;
$g_redirect_filename_r = undef;
}
if (defined $filename) {
iout ("close(\$sh2p_handle);\n");
iout ("undef \$sh2p_handle;\n\n");
}
return 1; # In case it gets used as a token
}
############################################################################
sub Query_redirection {
my ($mode) = @_;
if ($mode eq 'w') {
return $g_redirect_filename_w;
}
else {
return $g_redirect_filename_r;
}
}
############################################################################
sub Handle_variable {
lib/App/sh2p/Handlers.pm view on Meta::CPAN
elsif ( $token =~ s/^\$!(\w+)\[.*\]/\@$1/ ) { # ksh92 & bash !
# Find indexes of set variables
iout "sh2p_array_count($token)";
store_sh2p_array_count ($token);
return 1;
}
elsif ( substr($token, 0, 3) eq '$((' ) {
# Calculation
$token =~ s/\$\(\((.*)\)\)/$1/g;
}
elsif ( substr($token, 0, 2) eq '$(' ) {
# Back-ticks
$token =~ s/\$\((.*)\)/`$1`/g;
}
elsif ( $token =~ /\[(.+)\]/) {
#print STDERR "Handle_variable array <$1>\n";
my $idx = $1;
# The shell allows a variable index without a '$'
if ($idx =~ /^[[:alpha:]_]/) { # No '$' [count + 1] or even [i]
$idx = "\$$idx";
$token =~ s/\[(.+)\]/[$idx]/;
}
elsif ( $idx eq '*' || $idx eq '@' ) {
# How do we find if we are quoted?
$token =~ s/\$(.+)\[.*\]/$1/;
if (query_in_quotes()) {
if ($idx eq '@') {
$token = "\"\@$token\"";
}
else {
my $glue = get_special_var('IFS');
$glue =~ s/^([\"\'])(.*)\1$/$2/; # Not certain there are quotes
$glue = substr($glue,0,1);
$token = "join(\"$glue\",\@$token)";
}
}
else {
$token = "\@$token";
}
}
}
out $token;
return 1;
}
############################################################################
sub Handle_expansion {
my ($token) = @_;
my $ntok;
#print STDERR "Handle_expansion: <$token>\n";
# my @caller = caller();
# print STDERR "Called from @caller\n";
# Strip out the braces
# $2: (.*?) replaced with (.*) 0.04
$token =~ s/\$\{(.*?)\}(.*)/\$$1/;
my $suffix = $2;
# Arrays
if ($token =~ /\w+\[.*\]/) {
$ntok = Handle_variable($token);
}
elsif ( $token =~ /(\w+)([:?\-=+]{1,2})([^:?\-=+]+)/ ) {
my $var = '$'.$1;
my $qual = $2;
my $extras = $3;
#print STDERR "Handle_expansion <$var><$2><$3>\n";
if (my $new_var = get_special_var($var)) {
$var = $new_var;
}
# Remove the :
# Done this way in case further modification is required
$qual =~ s/^://;
if ($qual eq '?') {
if (! $extras) {
$extras = "'$var undef or not set'";
}
# $extras should already be quoted
out ("print STDERR $extras,\"\\n\" if (! defined $var or ! $var);");
}
elsif ($qual eq '=') {
out ("(defined $var or $var) || $var = ");
my @tmp = ($extras);
my @types = App::sh2p::Parser::identify (1, @tmp);
App::sh2p::Parser::convert (@tmp, @types);
}
elsif ($qual eq '-') {
out ("(defined $var or $var) || ");
my @tmp = ($extras);
my @types = App::sh2p::Parser::identify (1, @tmp);
App::sh2p::Parser::convert (@tmp, @types);
}
elsif ($qual eq '+') {
out ("(! defined $var or ! $var) || ");
my @tmp = ($extras);
my @types = App::sh2p::Parser::identify (1, @tmp);
App::sh2p::Parser::convert (@tmp, @types);
}
else {
error_out ("Pattern $qual not currently supported");
out ($token);
}
$ntok = 1;
}
elsif ( $token =~ s/^\$#(.+)/\$$1/ ) {
out "length($token)";
$ntok = 1;
lib/App/sh2p/Handlers.pm view on Meta::CPAN
&{$perlbi[0]}(@cmd);
if ($rest) {
unless ($preamble eq $rest &&
($rest eq '"' or $rest eq "'"))
{
out '.';
interpolation ($rest);
}
}
}
else {
out " $tok ";
}
}
else {
out " $tok";
out ' ' unless substr($tok,-1) eq "\n"; # 0.04
}
return $ntok;
}
############################################################################
sub Handle_subshell {
my ($subshell) = @_;
error_out "Subshell: ($subshell)";
iout "{\n";
inc_indent();
inc_block_level(); # 0.05
mark_subshell();
iout "local \%ENV;\n"; # one of the features of a subshell
# Search for different statements
for my $tok (split (';', $subshell)) {
# should probably be done in sh2p
my @tokens = App::sh2p::Parser::tokenise ($tok);
my @types = App::sh2p::Parser::identify (0, @tokens);
#print_types_tokens (\@types,\@tokens);
App::sh2p::Parser::convert (@tokens, @types);
}
dec_indent();
dec_block_level(); # 0.05
unmark_subshell();
out "}\n";
}
############################################################################
sub interpolation {
my ($string) = @_;
my $delimiter = '';
#print STDERR "interpolation: <$string>\n";
#my @caller = caller();
#print STDERR "@caller\n";
# single quoted string
if ($string =~ /^(\'.*\')(.*)/) {
my $single = $1;
$string = $2;
if ($string) {
out "$single.";
}
else {
out "$single";
return;
}
}
if ( substr($string,0,1) eq '"') {
# strip out leading & trailing double quotes
$string =~ s/^\"(.*)\"$/$1/;
set_in_quotes();
}
# Insert leading quote to balance end
# Why? Because the string might not be quoted
out ('"');
my @chars = split '', $string;
for (my $i = 0; $i < @chars; $i++) {
if ($chars[$i] eq '\\') { # esc
out $chars[$i];
$i++;
out $chars[$i];
}
elsif ($chars[$i] eq '"' and !query_in_quotes()) {
# embedded quote 0.04
out '\\"';
}
elsif ($chars[$i] eq '`') {
out '".';
$delimiter = '`';
my $cmd = $chars[$i];
$i++;
while ($i < @chars) {
$cmd .= $chars[$i];
last if ($chars[$i] eq $delimiter);
$i++; # Position change January 2009
}
Handle_delimiter ($cmd);
out '."' if $i < (@chars-1);
}
elsif ($chars[$i] eq '$') {
my $token = $chars[$i];
$i++;
if ($chars[$i] eq '(') {
lib/App/sh2p/Handlers.pm view on Meta::CPAN
}
else {
iout "@args $last";
}
$ntok += @args; # January 2009
}
else {
my @perlbi;
my $user_function = 0;
# pipes?
# This loop replaces the grep below (it was detecting | inside quotes)
for my $tok (@args) {
next if $tok =~ /^([\'\"]).*\1$/;
if ($tok =~ /\|[^\|]/) { # RE change 0.05
$ntok = App::sh2p::Parser::analyse_pipeline (@args);
return $ntok;
}
}
#if ( grep /\|[^\|]/, @args) { # RE change 0.05
# $ntok = App::sh2p::Parser::analyse_pipeline (@args);
# return $ntok;
#}
# shortcuts or break? 0.05
my @types = App::sh2p::Parser::identify (1, @args);
my $i;
for ($i = 0;$i < @types; $i++) {
if ($types[$i][0] eq 'OPERATOR') {
no_semi_colon();
splice (@args, $i);
last
}
elsif ($types[$i][0] eq 'BREAK') {
splice (@args, $i);
last
}
}
# Strip quotes January 2009
my $name = $args[0];
$name =~ s/^([\"\'])(.*)\1$/$2/;
#print STDERR "Handle_external: <$name>\n";
# If a user function, then call it as a subroutine
if (is_user_function($name)) {
$func = $name;
shift @args;
$user_function = 1;
$ntok++;
}
elsif (@perlbi = App::sh2p::Parser::get_perl_builtin($name)) {
# Do my best to trap unnecessary child processes
$ntok = &{$perlbi[0]}(@_);
return $ntok;
}
if (is_break($args[0])) {
my @caller = caller();
print STDERR "@caller\n";
error_out ("++++ Internal error: Invalid break in Handle_external");
}
my $append = '';
$append = ';' if query_semi_colon();
iout "$func (";
# Parse arguments
if ( $user_function ) {
if (@args) {
for (my $i = 0; $i < @args; $i++) {
$ntok++;
# Escape embedded quotes
$args[$i] =~ s/\"/\\\"/g;
#"help syntax highlighter
$args[$i] = "\"$args[$i]\"";
$args[$i] .= ',' if $i < $#args;
}
interpolation ("@args");
}
}
else {
for my $arg (@args) {
$ntok++;
# Escape embedded quotes
$arg =~ s/\"/\\\"/g;
#"help syntax highlighter
}
interpolation ("@args");
}
# Added 0.03
if ($func eq 'system') {
my $context = App::sh2p::Compound::get_context();
if ($context eq 'if' || $context eq 'while') {
$append .= '== 0';
}
elsif ($context eq 'until') {
$append .= '!= 0';
}
}
out ")$append $last"; # Moved 0.04
out "\n" if query_semi_colon();
}
return $ntok;
}
##############################################################
sub Handle_Glob {
my (@tokens) = @_;
my $ntok = @tokens;
local $" = '';
iout "(glob(\"@tokens\"))";
return $ntok;
}
############################################################################
sub Handle_unknown {
my ($token) = @_;
# Don't quote if numeric or already has quotes
if ($token =~ /^[-+]?\d+$/ || $token =~ /^\".*\"$/) {
out "$token";
}
else {
#my @caller = caller();
#print STDERR "Handle_unknown token: <$token> @caller\n";
out "\"$token\"";
}
return 1;
}
############################################################################
sub store_subs {
my ($name, $subroutine) = @_;
$g_subs{$name} = $subroutine;
}
sub write_subs {
if (%g_subs) {
out "\n#\n# Subroutines added by sh2p\n#\n";
}
for my $sub (sort keys %g_subs) {
out $g_subs{$sub};
}
}
############################################################################
sub store_sh2p_array_count {
return if exists $g_subs{sh2p_array_count};
$g_subs{sh2p_array_count} = << 'AC_HERE';
############################################################################
# Generated when ${!array[@]} is used
sub sh2p_array_count {
my @array = @_;
my $result = '';
for (my $i=0; $i < @array; $i++) {
$result .= "$i " if defined $array[$i];
}
# Should return a space separated scalar
chop $result; # remove final space
return $result;
}
AC_HERE
}
############################################################################
1;
__END__
=head1 Summary
package App::sh2p::Handlers;
( run in 1.913 second using v1.01-cache-2.11-cpan-97f6503c9c8 )