File Coverage

blib/lib/Psh/Builtins/Tieopt.pm
Criterion Covered Total %
statement 62 69 89.8
branch 37 48 77.0
condition 10 14 71.4
subroutine 3 3 100.0
pod 0 1 0.0
total 112 135 82.9


line stmt bran cond sub pod time code
1             package Psh::Builtins::Tieopt;
2              
3             require Psh;
4             require Psh::Util;
5             require Psh::Support::TiedOption;
6             require Psh::Options;
7              
8             =item * C
9              
10             =item * C
11              
12             =item * C
13              
14             Ties the option named NAME to the global variable $VAR, @VAR or %VAR
15              
16             =item * C
17              
18             Ties the option named NAME to the global variable named $NAME, @NAME, or %NAME, depending on the option's type.
19              
20             =item * C
21              
22             Unties the global variable named $VAR
23             Note that you can simply use perl's built-in C
24              
25             =cut
26              
27             sub bi_tieopt {
28 20     20 0 2886 my $line = shift;
29 20         19 my @words = @{shift()};
  20         38  
30              
31 20         20 my ($untie, $name, $var, $actual_type, $requested_type);
32              
33 20         58 my %var_types = (
34             '$' => 'SCALAR',
35             '@' => 'ARRAY',
36             '%' => 'HASH',
37             );
38              
39             # untie NAME
40             # untie $VAR
41 20 100       70 if ($words[0] =~ /^-u$/i) {
    100          
    50          
42 10         12 $untie = 1;
43              
44 10         11 $var = $words[1];
45 10 100       33 if ($var =~ /^(\$|\@|\%)/) {
46 5         11 $requested_type = $var_types{$1};
47             }
48 10         62 $var =~ s/\W//g;
49 10         16 $name = $var;
50              
51             }
52              
53             # tieopt NAME
54             # tieopt $VAR
55             elsif (@words == 1) {
56 5         6 $name = $words[0];
57              
58 5 100       21 if ($name =~ /^(\$|\@|\%)/) {
59 3         8 $requested_type = $var_types{$1};
60             }
61 5         12 $name =~ s/\W//g;
62              
63 5         8 $var = $name;
64             }
65             # tieopt NAME $VAR
66             elsif (@words == 2) {
67 5         10 ($name, $var) = @words;
68              
69 5 50       19 if ($var =~ /^(\$|\@|\%)/) {
70 5         10 $requested_type = $var_types{$1};
71             }
72 5         10 $name =~ s/\W//g;
73 5         27 $var =~ s/\W//g;
74             }
75             else {
76 0         0 return;
77             }
78              
79              
80 20         56 $curr_val = Psh::Options::get_option($name);
81              
82 20         33 $actual_type = ref $curr_val;
83              
84 20 100       32 if (defined $curr_val) {
85 19 100       28 if (ref $curr_val) {
86 12 100 66     50 if (ref $curr_val eq 'ARRAY' and @$curr_val) {
87 8         8 $actual_type = 'ARRAY';
88             }
89 12 50 66     41 if (ref $curr_val eq 'HASH' and keys %curr_val) {
90 0         0 $actual_type = 'HASH';
91             }
92             }
93             else {
94 7 50       14 if ($curr_val) {
95 7         10 $actual_type = 'SCALAR';
96             }
97             }
98             }
99              
100 20   100     60 $requested_type ||= $actual_type || 'SCALAR';
      66        
101              
102 20 100       33 if ($untie) {
103 1     1   1507 no strict 'refs';
  1         2  
  1         147  
104 10 100       22 if ($requested_type eq 'SCALAR') {
105 4         5 untie ${"$Psh::PerlEval::current_package\:\:$name"};
  4         24  
106             }
107 10 100       39 if ($requested_type eq 'ARRAY') {
108              
109 4         3 untie @{"$Psh::PerlEval::current_package\:\:$name"};
  4         26  
110             }
111 10 100       39 if ($requested_type eq 'HASH') {
112 2         3 untie %{"$Psh::PerlEval::current_package\:\:$name"};
  2         21  
113             }
114             }
115             else {
116 10 50 66     39 if ($actual_type and $actual_type ne $requested_type) {
117 0 0       0 if ($requested_type eq 'ARRAY') {
    0          
118 0         0 Psh::Util::print_error_i18n('bi_tieopt_badtype_array', $name);
119             }
120             elsif ($requested_type eq 'HASH') {
121 0         0 Psh::Util::print_error_i18n('bi_tieopt_badtype_hash', $name);
122             }
123             else {
124 0         0 Psh::Util::print_error_i18n('bi_tieopt_badtype_scalar', $name);
125             }
126 0         0 return;
127             }
128             # print STDERR "tying option: $name to \${$Psh::PerlEval::current_package\:\:$var}\n" if $requested_type eq 'SCALAR';
129             # print STDERR "tying option: $name to \@{$Psh::PerlEval::current_package\:\:$var}\n" if $requested_type eq 'ARRAY';
130             # print STDERR "tying option: $name to \%{$Psh::PerlEval::current_package\:\:$var}\n" if $requested_type eq 'HASH';
131              
132             {
133              
134             # Tie the $name to $var
135 1     1   5 no strict 'refs';
  1         2  
  1         231  
  10         10  
136 10 100       19 if ($requested_type eq 'SCALAR') {
137 4 100       7 Psh::Options::set_option($name, '') unless $actual_type;
138 4         5 tie ${"$Psh::PerlEval::current_package\:\:$var"}, 'Psh::Support::TiedOption::Scalar', $name;
  4         26  
139             }
140 10 100       20 if ($requested_type eq 'ARRAY') {
141 4 50       9 Psh::Options::set_option($name, []) unless $actual_type;
142 4         3 tie @{"$Psh::PerlEval::current_package\:\:$var"}, 'Psh::Support::TiedOption::Array', $name;
  4         28  
143              
144             }
145 10 100       35 if ($requested_type eq 'HASH') {
146 2 50       5 Psh::Options::set_option($name, {}) unless $actual_type;
147 2         4 tie %{"$Psh::PerlEval::current_package\:\:$var"}, 'Psh::Support::TiedOption::Hash', $name;
  2         14  
148             }
149             }
150             }
151             }
152              
153             1;