line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::Info; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
@ISA = qw( Exporter ); |
4
|
|
|
|
|
|
|
@EXPORT = qw( readconfig ); |
5
|
|
|
|
|
|
|
@EXPORT_OK = qw( readconfig stringconfig $minus_one_indent_rx ); |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
$VERSION = '0.102'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
require Exporter; |
10
|
1
|
|
|
1
|
|
68363
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
31
|
|
11
|
1
|
|
|
1
|
|
534
|
use Text::Tabs; |
|
1
|
|
|
|
|
764
|
|
|
1
|
|
|
|
|
125
|
|
12
|
1
|
|
|
1
|
|
8
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
54
|
|
13
|
1
|
|
|
1
|
|
5
|
use Carp qw( verbose confess ); |
|
1
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
117
|
|
14
|
1
|
|
|
1
|
|
488
|
use IO::File; |
|
1
|
|
|
|
|
8730
|
|
|
1
|
|
|
|
|
116
|
|
15
|
1
|
|
|
1
|
|
9
|
use Scalar::Util qw( weaken ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
136
|
|
16
|
|
|
|
|
|
|
my $iostrings; |
17
|
|
|
|
|
|
|
our $allow_minus_one_indent = qr/class /; |
18
|
|
|
|
|
|
|
our $allow_plus_one_indent = qr/service-policy |quit$/; |
19
|
|
|
|
|
|
|
our $bad_indent_policy = 'DIE'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
BEGIN { |
23
|
1
|
|
|
1
|
|
76
|
eval " use IO::String "; |
|
1
|
|
|
1
|
|
223
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
24
|
1
|
50
|
|
|
|
183
|
$iostrings = $@ ? 0 : 1; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $debug_get = 0; |
29
|
|
|
|
|
|
|
my $debug_mget = 0; |
30
|
|
|
|
|
|
|
my $debug_set = 0; |
31
|
|
|
|
|
|
|
my $debug_context = 0; |
32
|
|
|
|
|
|
|
my $debug_text = 0; |
33
|
|
|
|
|
|
|
my $ddata = $debug_get |
34
|
|
|
|
|
|
|
|| $debug_mget |
35
|
|
|
|
|
|
|
|| $debug_set |
36
|
|
|
|
|
|
|
|| $debug_context |
37
|
|
|
|
|
|
|
|| $debug_text |
38
|
|
|
|
|
|
|
|| 0; # add debugging data to data structures |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $spec = qr{^ }; |
41
|
|
|
|
|
|
|
my $text = " text"; |
42
|
|
|
|
|
|
|
my $subs = " subs"; |
43
|
|
|
|
|
|
|
my $next = " next"; |
44
|
|
|
|
|
|
|
my $cntx = " cntx"; |
45
|
|
|
|
|
|
|
my $word = " word"; |
46
|
|
|
|
|
|
|
my $seqn = " seqn"; |
47
|
|
|
|
|
|
|
my $dupl = " dupl"; |
48
|
|
|
|
|
|
|
my $debg = " debg"; |
49
|
|
|
|
|
|
|
my $bloc = " bloc"; |
50
|
|
|
|
|
|
|
my $UNDEFDESC = "! undefined\n"; |
51
|
|
|
|
|
|
|
my $undef = bless { $debg => $UNDEFDESC, $text => '' }, __PACKAGE__; |
52
|
|
|
|
|
|
|
my $dseq = "O0000000"; |
53
|
|
|
|
|
|
|
our $nonext; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my $line; |
56
|
|
|
|
|
|
|
my $fh; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
use overload |
59
|
1
|
|
|
|
|
8
|
'bool' => \&defined, |
60
|
|
|
|
|
|
|
'""' => \&text, |
61
|
1
|
|
|
1
|
|
1331
|
'fallback' => 1; |
|
1
|
|
|
|
|
987
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub stringconfig { |
64
|
0
|
0
|
|
0
|
0
|
|
Carp::croak 'IO::Strings need to be installed to use "stringconfig"' |
65
|
|
|
|
|
|
|
. ' install it or use "readconfig" instead.' unless $iostrings; |
66
|
0
|
|
|
|
|
|
readconfig(IO::String->new(join("\n", @_))); |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub readconfig { |
70
|
0
|
|
|
0
|
0
|
|
my ($file) = @_; |
71
|
0
|
0
|
|
|
|
|
$fh = ref($file) ? $file : IO::File->new($file, "r"); |
72
|
0
|
|
|
|
|
|
$line = <$fh>; |
73
|
0
|
|
|
|
|
|
return rc1(0, 'aaaa', $undef, "! whole enchalada\n"); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub rc1 { |
77
|
0
|
|
|
0
|
0
|
|
my ($indent, $seq, $parent, $dcon) = @_; |
78
|
0
|
|
|
|
|
|
my $config = bless { $bloc => 1 }, __PACKAGE__; |
79
|
0
|
0
|
|
|
|
|
$config->{$debg} = "BLOCK:$dseq:$dcon" if $ddata; |
80
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
$config->{$cntx} = $parent; |
82
|
0
|
|
|
|
|
|
weaken $config->{$cntx}; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
$dseq ++; |
85
|
0
|
|
|
|
|
|
my ($last, $prev, $ciscobug); |
86
|
0
|
|
|
|
|
|
for ( ; $line; $prev = $line, $line = <$fh> ) { |
87
|
0
|
|
|
|
|
|
$_ = $line; |
88
|
0
|
|
|
|
|
|
s/^( *)//; |
89
|
0
|
|
|
|
|
|
my $in = length($1); |
90
|
0
|
|
|
|
|
|
s/^(no +)//; |
91
|
|
|
|
|
|
|
#新行向右缩进 |
92
|
0
|
0
|
|
|
|
|
if ( $in > $indent ) { |
|
|
0
|
|
|
|
|
|
93
|
|
|
|
|
|
|
#如果存在上下文,则将新行视为上一配置的子节点; |
94
|
0
|
0
|
|
|
|
|
if ( $last ) { |
95
|
0
|
|
|
|
|
|
$last->{$subs} = rc1($in, "$last->{$seqn}aaa", $last, $line); |
96
|
0
|
|
|
|
|
|
undef $last; |
97
|
0
|
0
|
|
|
|
|
redo if $line; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
else { |
100
|
|
|
|
|
|
|
#正常缩进不会出现此情况,以下代码用来捕捉特例缩进代码 |
101
|
0
|
0
|
0
|
|
|
|
if ( $indent + 1 == $in && $allow_plus_one_indent && $line =~ /^\s*$allow_plus_one_indent/ ) { |
|
|
|
0
|
|
|
|
|
102
|
0
|
|
|
|
|
|
$indent = $indent + 1; |
103
|
0
|
|
|
|
|
|
redo; |
104
|
|
|
|
|
|
|
} |
105
|
0
|
0
|
0
|
|
|
|
if ( $indent != 0 || ($prev ne "!\n" && $prev !~ /^!.*$/) ) { |
|
|
|
0
|
|
|
|
|
106
|
0
|
0
|
|
|
|
|
if ( $bad_indent_policy eq 'IGNORE' ) { |
|
|
0
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# okay then |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
elsif ( $bad_indent_policy eq 'WARN' ) { |
110
|
0
|
|
|
|
|
|
warn "Unexpected indentation change <$.:$_>"; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
else { |
113
|
0
|
|
|
|
|
|
confess "Unexpected indentation change <$.:$_>"; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
} |
116
|
0
|
|
|
|
|
|
$ciscobug = 1; |
117
|
0
|
|
|
|
|
|
$indent = $in; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
#新行想左缩进 |
121
|
|
|
|
|
|
|
elsif ( $in < $indent ) { |
122
|
|
|
|
|
|
|
#匹配到异常缩进并且重写缩进为0 |
123
|
0
|
0
|
0
|
|
|
|
if ( $ciscobug && $in == 0 ) { |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
124
|
0
|
|
|
|
|
|
$indent = 0; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
#存在上下文环境 |
127
|
|
|
|
|
|
|
elsif ( $last && $indent - 1 == $in && $allow_minus_one_indent && $line =~ /^\s*$allow_minus_one_indent/ ) { |
128
|
0
|
0
|
|
|
|
|
confess unless $last->{$seqn}; |
129
|
0
|
|
|
|
|
|
$last->{$subs} = rc1($in, "$last->{$seqn}aaa", $last, $line); |
130
|
0
|
|
|
|
|
|
undef $last; |
131
|
0
|
0
|
|
|
|
|
redo if $line; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
else { |
134
|
0
|
|
|
|
|
|
return $config; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
0
|
0
|
|
|
|
|
next if /^$/; |
138
|
0
|
0
|
|
|
|
|
next if /^\s*!/; |
139
|
0
|
|
|
|
|
|
my $context = $config; |
140
|
0
|
|
|
|
|
|
my (@x) = split; |
141
|
0
|
|
|
|
|
|
my $owords = @x; |
142
|
0
|
|
0
|
|
|
|
while ( @x && ref $context->{$x[0]} ) { |
143
|
0
|
|
|
|
|
|
$context = $context->{$x[0]}; |
144
|
0
|
|
|
|
|
|
shift @x; |
145
|
|
|
|
|
|
|
} |
146
|
0
|
0
|
|
|
|
|
if ( ! @x ) { |
|
|
0
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# A duplicate line. Not fun. |
148
|
|
|
|
|
|
|
# As far as we know this can only occur as a remark inside |
149
|
|
|
|
|
|
|
# filter list. |
150
|
|
|
|
|
|
|
# Q: what's the point of keeping track of these? Need to be |
151
|
|
|
|
|
|
|
# able to accurately dump filter list definitions |
152
|
|
|
|
|
|
|
# |
153
|
|
|
|
|
|
|
$context->{$dupl} = [] |
154
|
0
|
0
|
|
|
|
|
unless $context->{$dupl}; |
155
|
|
|
|
|
|
|
my $n = bless { |
156
|
|
|
|
|
|
|
$ddata |
157
|
|
|
|
|
|
|
? ($debg => "$dseq:DUP:$line", |
158
|
0
|
0
|
|
|
|
|
$word => $context->{$word},) |
159
|
|
|
|
|
|
|
: (), |
160
|
|
|
|
|
|
|
}, __PACKAGE__; |
161
|
0
|
|
|
|
|
|
$dseq ++; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
push(@{ $context->{$dupl} }, $n); |
|
0
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
$context = $n; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
elsif ( defined $context->{$x[0]} ) { |
167
|
0
|
|
|
|
|
|
confess "already $.: '$x[0]' $line"; |
168
|
|
|
|
|
|
|
} |
169
|
0
|
|
|
|
|
|
while ( @x ) { |
170
|
0
|
|
|
|
|
|
my $x = shift @x; |
171
|
0
|
0
|
|
|
|
|
confess unless defined $x; |
172
|
0
|
0
|
|
|
|
|
confess unless defined $dseq; |
173
|
0
|
0
|
|
|
|
|
$line = "" unless defined $line; |
174
|
0
|
0
|
|
|
|
|
$context = $context->{$x} = bless { |
175
|
|
|
|
|
|
|
$ddata |
176
|
|
|
|
|
|
|
? ($debg => "$dseq:$x:$line", |
177
|
|
|
|
|
|
|
$word => $x,) |
178
|
|
|
|
|
|
|
: (), |
179
|
|
|
|
|
|
|
}, __PACKAGE__; |
180
|
0
|
|
|
|
|
|
$dseq ++; |
181
|
|
|
|
|
|
|
} |
182
|
0
|
|
|
|
|
|
$context->{$seqn} = $seq ++; |
183
|
0
|
|
|
|
|
|
$context->{$text} = $line; |
184
|
0
|
0
|
|
|
|
|
confess if $context->{$cntx}; |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
$context->{$cntx} = $config; |
187
|
0
|
|
|
|
|
|
weaken $context->{$cntx}; |
188
|
|
|
|
|
|
|
|
189
|
0
|
0
|
|
|
|
|
unless ( $nonext ) { |
190
|
0
|
0
|
|
|
|
|
if ( $last ) { |
191
|
0
|
|
|
|
|
|
$last->{$next} = $context; |
192
|
0
|
|
|
|
|
|
weaken $last->{$next}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
else { |
195
|
0
|
|
|
|
|
|
$config->{$next} = $context; |
196
|
0
|
|
|
|
|
|
weaken $config->{$next}; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
|
$last = $context; |
201
|
|
|
|
|
|
|
|
202
|
0
|
0
|
0
|
|
|
|
if ( $line && |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
203
|
|
|
|
|
|
|
($line =~ /(\^C)/ && $line !~ /\^C.*\^C/) |
204
|
|
|
|
|
|
|
|| |
205
|
|
|
|
|
|
|
($line =~ /banner [a-z\-]+ ((?!\^C).+)/) ) { |
206
|
|
|
|
|
|
|
# |
207
|
|
|
|
|
|
|
# big special case for banners 'cause they don't follow |
208
|
|
|
|
|
|
|
# normal indenting rules |
209
|
|
|
|
|
|
|
# |
210
|
0
|
0
|
|
|
|
|
die unless defined $1; |
211
|
0
|
|
|
|
|
|
my $sep = qr/\Q$1\E/; |
212
|
0
|
|
|
|
|
|
my $sub = $last->{$subs} = bless { $bloc => 1 }, __PACKAGE__; |
213
|
0
|
|
|
|
|
|
$sub->{$cntx} = $last; |
214
|
0
|
|
|
|
|
|
weaken $sub->{$cntx}; |
215
|
0
|
|
|
|
|
|
my $subnull = $sub->{''} = bless { $bloc => 1, $dupl => [] }, __PACKAGE__; |
216
|
0
|
|
|
|
|
|
$subnull->{$cntx} = $sub; |
217
|
0
|
|
|
|
|
|
weaken $subnull->{$cntx}; |
218
|
0
|
|
|
|
|
|
for ( ;; ) { |
219
|
0
|
|
|
|
|
|
$line = <$fh>; |
220
|
0
|
0
|
|
|
|
|
last unless $line; |
221
|
0
|
0
|
|
|
|
|
my $l = bless { |
222
|
|
|
|
|
|
|
$ddata ? ($debg => "$dseq:DUP:$line") : (), |
223
|
|
|
|
|
|
|
}, __PACKAGE__; |
224
|
0
|
|
|
|
|
|
$dseq ++; |
225
|
0
|
|
|
|
|
|
$l->{$seqn} = $seq ++; |
226
|
0
|
|
|
|
|
|
$l->{$text} = $line; |
227
|
0
|
|
|
|
|
|
$l->{$cntx} = $subnull; |
228
|
0
|
|
|
|
|
|
weaken($l->{$cntx}); |
229
|
0
|
|
|
|
|
|
push(@{ $subnull->{$dupl} }, $l); |
|
0
|
|
|
|
|
|
|
230
|
0
|
0
|
|
|
|
|
last if $line =~ /$sep[\r]?$/; |
231
|
|
|
|
|
|
|
} |
232
|
0
|
0
|
0
|
|
|
|
warn "parse probably failed" |
233
|
|
|
|
|
|
|
unless $line && $line =~ /$sep[\r]?$/; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
} |
236
|
0
|
|
|
|
|
|
return $config; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
#sub word { $_[0]->{$word} }; |
240
|
0
|
|
|
0
|
0
|
|
sub block { $_[0]->{$bloc} } |
241
|
0
|
0
|
0
|
0
|
0
|
|
sub seqn { $_[0]->{$seqn} || $_[0]->endpt->{$seqn} || confess }; |
242
|
0
|
0
|
0
|
0
|
0
|
|
sub subs { $_[0]->{$subs} || $_[0]->zoom->{$subs} || $undef }; |
243
|
0
|
0
|
0
|
0
|
0
|
|
sub next { $_[0]->{$next} || $_[0]->zoom->{$next} || $undef }; |
244
|
|
|
|
|
|
|
#sub undefined { $_[0] eq $undef } |
245
|
|
|
|
|
|
|
#sub defined { $_[0] ne $undef } |
246
|
0
|
0
|
|
0
|
0
|
|
sub defined { $_[0]->{$debg} ? $_[0]->{$debg} ne $UNDEFDESC : 1 } |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub destroy { |
249
|
0
|
|
|
0
|
0
|
|
warn "Cisco::Reconfig::destroy is deprecated"; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub single { |
253
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
254
|
0
|
0
|
|
|
|
|
return $self if defined $self->{$text}; |
255
|
0
|
|
|
|
|
|
my (@p) = grep (! /$spec/o, keys %$self); |
256
|
0
|
0
|
|
|
|
|
return undef if @p > 1; |
257
|
0
|
0
|
|
|
|
|
return $self unless @p; |
258
|
0
|
|
0
|
|
|
|
return $self->{$p[0]}->single || $self; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub kids { |
262
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
263
|
0
|
0
|
|
|
|
|
return $self if ! $self; |
264
|
0
|
|
|
|
|
|
my (@p) = $self->sortit(grep (! /$spec/o, keys %$self)); |
265
|
0
|
0
|
|
|
|
|
return $self if ! @p; |
266
|
0
|
|
|
|
|
|
return(map { $self->{$_} } @p); |
|
0
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub zoom { |
270
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
271
|
0
|
0
|
|
|
|
|
return $self if defined $self->{$text}; |
272
|
0
|
|
|
|
|
|
my (@p) = $self->sortit(grep (! /$spec/o, keys %$self)); |
273
|
0
|
0
|
|
|
|
|
return $self if @p > 1; |
274
|
0
|
0
|
|
|
|
|
return $self unless @p; |
275
|
0
|
|
|
|
|
|
return $self->{$p[0]}->zoom; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub endpt { |
279
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
280
|
0
|
0
|
|
|
|
|
return $self if ! $self; |
281
|
0
|
|
|
|
|
|
my (@p) = grep (! /$spec/o, keys %$self); |
282
|
0
|
0
|
0
|
|
|
|
return $self if defined($self->{$text}) && ! @p; |
283
|
0
|
0
|
|
|
|
|
confess unless @p; |
284
|
0
|
|
|
|
|
|
return $self->{$p[0]}->endpt; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub text { |
289
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
290
|
0
|
0
|
|
|
|
|
return '' unless $self; |
291
|
0
|
0
|
|
|
|
|
if ( defined $self->{$text} ) { |
292
|
|
|
|
|
|
|
return $debug_text |
293
|
|
|
|
|
|
|
? $self->{$word} . " " . $self->{$text} |
294
|
0
|
0
|
|
|
|
|
: $self->{$text}; |
295
|
|
|
|
|
|
|
} |
296
|
0
|
|
|
|
|
|
my (@p) = $self->sortit(grep (! /$spec/o, keys %$self)); |
297
|
0
|
0
|
|
|
|
|
if ( @p > 1 ) { |
|
|
0
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# |
299
|
|
|
|
|
|
|
# This is nasty because the lines may not be ordered |
300
|
|
|
|
|
|
|
# in the tree-hiearchy used by Cisco::Reconfig |
301
|
|
|
|
|
|
|
# |
302
|
0
|
|
|
|
|
|
my %temp = map { $self->{$_}->sequenced_text(0) } @p; |
|
0
|
|
|
|
|
|
|
303
|
0
|
|
|
|
|
|
return join('', map { $temp{$_} } sort keys %temp); |
|
0
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
elsif ( $self->{$dupl} ) { |
306
|
0
|
0
|
|
|
|
|
return join('', map { $_->{$word} . " " . $_->{$text} } @{ $self->{$dupl} }) |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
if $debug_text; |
308
|
0
|
|
|
|
|
|
return join('', map { $_->{$text} } @{ $self->{$dupl} }); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
} |
310
|
0
|
0
|
|
|
|
|
confess unless @p; |
311
|
0
|
|
|
|
|
|
return $self->{$p[0]}->text; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
sub sequenced_text { |
315
|
0
|
|
|
0
|
0
|
|
my ($self, $all) = @_; |
316
|
0
|
|
|
|
|
|
my @t = (); |
317
|
0
|
0
|
|
|
|
|
if ( defined $self->{$text} ) { |
318
|
|
|
|
|
|
|
push(@t, $debug_text |
319
|
|
|
|
|
|
|
? ($self->seqn => $self->{$word} . " " . $self->{$text}) |
320
|
0
|
0
|
|
|
|
|
: ($self->seqn => $self->{$text})); |
321
|
|
|
|
|
|
|
} |
322
|
0
|
0
|
|
|
|
|
if ( exists $self->{$dupl} ) { |
323
|
|
|
|
|
|
|
push(@t, $debug_text |
324
|
0
|
|
|
|
|
|
? map { $_->seqn => $_->{$word} . " " . $_->{$text} } @{ $self->{$dupl} } |
|
0
|
|
|
|
|
|
|
325
|
0
|
0
|
|
|
|
|
: map { $_->seqn => $_->{$text} } @{ $self->{$dupl} }); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
} |
327
|
0
|
|
|
|
|
|
my (@p) = $self->sortit(grep (! /$spec/o, keys %$self)); |
328
|
0
|
0
|
|
|
|
|
if ( @p ) { |
329
|
|
|
|
|
|
|
# |
330
|
|
|
|
|
|
|
# This is nasty because the lines may not be ordered |
331
|
|
|
|
|
|
|
# in the tree-hiearchy used by Cisco::Reconfig |
332
|
|
|
|
|
|
|
# |
333
|
0
|
|
|
|
|
|
return(@t, map { $self->{$_}->sequenced_text($all) } @p); |
|
0
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
push(@t, $self->{$subs}->sequenced_text($all)) |
336
|
0
|
0
|
0
|
|
|
|
if $all && $self->{$subs}; |
337
|
0
|
0
|
|
|
|
|
return @t if @t; |
338
|
0
|
0
|
|
|
|
|
confess unless @p; |
339
|
0
|
|
|
|
|
|
return $self->{$p[0]}->sequenced_text($all); |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
sub alltext { |
343
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
344
|
0
|
0
|
|
|
|
|
return '' unless $self; |
345
|
0
|
|
|
|
|
|
my %temp = $self->sequenced_text(1); |
346
|
0
|
|
|
|
|
|
return join('', map { $temp{$_} } sort keys %temp); |
|
0
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub chomptext { |
350
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
351
|
0
|
|
|
|
|
|
my $t = $self->text; |
352
|
0
|
|
|
|
|
|
chomp($t); |
353
|
0
|
|
|
|
|
|
return $t; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub returns { |
357
|
0
|
|
|
0
|
0
|
|
my (@o) = @_; |
358
|
0
|
|
|
|
|
|
for my $o ( @o ) { |
359
|
0
|
0
|
0
|
|
|
|
$o .= "\n" |
360
|
|
|
|
|
|
|
if defined($o) && $o !~ /\n$/; |
361
|
|
|
|
|
|
|
} |
362
|
0
|
0
|
|
|
|
|
return $o[0] unless wantarray; |
363
|
0
|
|
|
|
|
|
return @o; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
sub openangle { |
367
|
0
|
|
0
|
0
|
0
|
|
my (@l) = grep (defined && / \S /, @_); |
368
|
0
|
|
|
|
|
|
my $x = 0; |
369
|
0
|
|
|
|
|
|
for my $l ( @l ) { |
370
|
0
|
|
|
|
|
|
substr($l, 0, 0) = (' ' x $x ++); |
371
|
|
|
|
|
|
|
} |
372
|
0
|
0
|
|
|
|
|
return $l[0] unless wantarray; |
373
|
0
|
|
|
|
|
|
return @l; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub closeangle { |
377
|
0
|
|
0
|
0
|
0
|
|
my (@l) = grep (defined && / \S /, @_); |
378
|
0
|
|
|
|
|
|
my $x = $#l; |
379
|
0
|
|
|
|
|
|
for my $l ( @l ) { |
380
|
0
|
|
|
|
|
|
substr($l, 0, 0) = (' ' x $x --); |
381
|
|
|
|
|
|
|
} |
382
|
0
|
0
|
|
|
|
|
return $l[0] unless wantarray; |
383
|
0
|
|
|
|
|
|
return @l; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub context { |
387
|
|
|
|
|
|
|
defined($_[0]->{$cntx}) |
388
|
|
|
|
|
|
|
? $_[0]->{$cntx} |
389
|
0
|
0
|
0
|
0
|
0
|
|
: $_[0]->endpt->{$cntx} |
390
|
|
|
|
|
|
|
|| ($_[0] ? confess "$_[0]" : $undef) |
391
|
|
|
|
|
|
|
}; |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# |
394
|
|
|
|
|
|
|
# interface Loopback7 |
395
|
|
|
|
|
|
|
# ip address x y |
396
|
|
|
|
|
|
|
# |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub setcontext { |
399
|
0
|
|
|
0
|
0
|
|
my ($self, @extras) = @_; |
400
|
0
|
0
|
|
|
|
|
print STDERR "\nSETCONTEXT\n" if $debug_context; |
401
|
0
|
0
|
|
|
|
|
unless ( $self->block ) { |
402
|
0
|
0
|
|
|
|
|
print STDERR "\nNOT_A_BLOCK $self->{$debg}\n" if $debug_context; |
403
|
0
|
|
|
|
|
|
$self = $self->context; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
printf STDERR "\nSELF %sCONTEXT %sCCONTEXT %sEXTRAS$#extras @extras\n", |
406
|
|
|
|
|
|
|
$self->{$debg}, $self->context->{$debg}, |
407
|
0
|
0
|
|
|
|
|
$self->context->context->{$debg} |
408
|
|
|
|
|
|
|
if $debug_context; |
409
|
0
|
|
|
|
|
|
my $x = $self->context; |
410
|
|
|
|
|
|
|
return(grep defined, |
411
|
|
|
|
|
|
|
$x->context->setcontext, |
412
|
0
|
0
|
|
|
|
|
trim($x->zoom->{$text}), |
413
|
|
|
|
|
|
|
@extras) |
414
|
|
|
|
|
|
|
if $x; |
415
|
0
|
|
|
|
|
|
return @extras; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub contextcount { |
419
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
420
|
0
|
|
|
|
|
|
my (@a) = $self->setcontext(@_); |
421
|
0
|
0
|
|
|
|
|
printf STDERR "CONTEXTCOUNT = %d\n", scalar(@a) if $debug_context; |
422
|
0
|
0
|
|
|
|
|
print STDERR map { "CC: $_\n" } @a if $debug_context; |
|
0
|
|
|
|
|
|
|
423
|
0
|
|
|
|
|
|
return scalar(@a); |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub unsetcontext { |
427
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
428
|
0
|
|
|
|
|
|
return(("exit") x $self->contextcount(@_)); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub teql { |
432
|
0
|
|
|
0
|
0
|
|
my ($self, $b) = @_; |
433
|
0
|
|
|
|
|
|
my $a = $self->text; |
434
|
0
|
|
|
|
|
|
$a =~ s/^\s+/ /g; |
435
|
0
|
|
|
|
|
|
$a =~ s/^ //; |
436
|
0
|
|
|
|
|
|
$a =~ s/ $//; |
437
|
0
|
|
|
|
|
|
chomp($a); |
438
|
0
|
|
|
|
|
|
$b =~ s/^\s+/ /g; |
439
|
0
|
|
|
|
|
|
$b =~ s/^ //; |
440
|
0
|
|
|
|
|
|
$b =~ s/ $//; |
441
|
0
|
|
|
|
|
|
chomp($b); |
442
|
0
|
|
|
|
|
|
return $a eq $b; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub set { |
446
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
447
|
0
|
|
|
|
|
|
my $new = pop; |
448
|
0
|
|
|
|
|
|
my (@designators) = @_; |
449
|
|
|
|
|
|
|
#my ($self, $designator, $new) = @_; |
450
|
0
|
0
|
|
|
|
|
print STDERR "\nSET\n" if $debug_set; |
451
|
0
|
0
|
|
|
|
|
return undef unless $self; |
452
|
0
|
|
|
|
|
|
my $old; |
453
|
|
|
|
|
|
|
#my @designators; |
454
|
0
|
0
|
|
|
|
|
print STDERR "\nSELF $self->{$debg}" if $debug_set; |
455
|
|
|
|
|
|
|
# move into the block if possible |
456
|
0
|
0
|
|
|
|
|
$self = $self->subs |
457
|
|
|
|
|
|
|
if $self->subs; |
458
|
0
|
0
|
|
|
|
|
print STDERR "\nSELF $self->{$debg}" if $debug_set; |
459
|
|
|
|
|
|
|
#if (ref $designator eq 'ARRAY') { |
460
|
|
|
|
|
|
|
# @designators = @$designator; |
461
|
|
|
|
|
|
|
# $old = $self->get(@designators); |
462
|
|
|
|
|
|
|
# $designator = pop(@designators); |
463
|
|
|
|
|
|
|
#} elsif ($designator) { |
464
|
|
|
|
|
|
|
# $old = $self->get($designator); |
465
|
|
|
|
|
|
|
#} else { |
466
|
|
|
|
|
|
|
# $old = $self; |
467
|
|
|
|
|
|
|
#} |
468
|
0
|
|
|
|
|
|
my $designator; |
469
|
0
|
0
|
|
|
|
|
if ( @designators ) { |
470
|
0
|
|
|
|
|
|
$old = $self->get(@designators); |
471
|
0
|
|
|
|
|
|
$designator = pop(@designators); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
else { |
474
|
0
|
|
|
|
|
|
$old = $self; |
475
|
|
|
|
|
|
|
} |
476
|
0
|
0
|
|
|
|
|
print STDERR "\nOLD $old->{$debg}" if $debug_set; |
477
|
0
|
|
|
|
|
|
my (@lines) = expand(grep (/./, split(/\n/, $new))); |
478
|
0
|
0
|
|
|
|
|
if ( $lines[0] =~ /^(\s+)/ ) { |
479
|
0
|
|
|
|
|
|
my $ls = $1; |
480
|
0
|
|
|
|
|
|
my $m = 1; |
481
|
0
|
0
|
|
|
|
|
map { substr($_, 0, length($ls)) eq $ls or $m = 0 } @lines; |
|
0
|
|
|
|
|
|
|
482
|
0
|
0
|
|
|
|
|
map { substr($_, 0, length($ls)) = '' } @lines |
|
0
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
if $m; |
484
|
|
|
|
|
|
|
} |
485
|
0
|
|
|
|
|
|
my $indent = (' ' x $self->contextcount(@designators)); |
486
|
0
|
|
|
|
|
|
for $_ ( @lines ) { |
487
|
0
|
|
|
|
|
|
s/(\S)\s+/$1 /g; |
488
|
0
|
|
|
|
|
|
s/\s+$//; |
489
|
0
|
0
|
|
|
|
|
$_ = 'exit' if /^\s*!\s*$/; |
490
|
0
|
|
|
|
|
|
$_ = "$indent$_"; |
491
|
|
|
|
|
|
|
} |
492
|
0
|
0
|
|
|
|
|
print STDERR "SET TO {\n@lines\n}\n" if $debug_set; |
493
|
0
|
|
|
|
|
|
my $desig = shift(@lines); |
494
|
0
|
|
|
|
|
|
my @o; |
495
|
0
|
0
|
|
|
|
|
undef $old |
496
|
|
|
|
|
|
|
if ! $old; |
497
|
0
|
0
|
0
|
|
|
|
if ( ! $old ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
498
|
0
|
0
|
|
|
|
|
print STDERR "NO OLD\n" if $debug_set; |
499
|
0
|
|
|
|
|
|
push(@o, openangle($self->setcontext(@designators))); |
500
|
0
|
|
|
|
|
|
push(@o, $desig); |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
elsif ( ! $designator && ! looks_like_a_block($desig, @lines) ) { |
503
|
0
|
0
|
0
|
|
|
|
if ( $self->block && $self->context ) { |
504
|
0
|
|
|
|
|
|
unshift(@lines, $desig); |
505
|
0
|
|
|
|
|
|
$old = $self->context; |
506
|
0
|
|
|
|
|
|
undef $desig; |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
else { |
509
|
0
|
|
|
|
|
|
unshift(@lines, $desig); |
510
|
0
|
0
|
|
|
|
|
print STDERR "IN NASTY BIT\n" if $debug_set; |
511
|
|
|
|
|
|
|
# |
512
|
|
|
|
|
|
|
# this is a messy situation: we've got a random |
513
|
|
|
|
|
|
|
# block of stuff to set inside a random block. |
514
|
|
|
|
|
|
|
# In theorey we could avoid the die, I'll leave |
515
|
|
|
|
|
|
|
# that as an exercise for the reader. |
516
|
|
|
|
|
|
|
# |
517
|
0
|
0
|
|
|
|
|
confess "You cannot set nested configurations with set(undef, \$config) -- use a designator on the set method" |
518
|
|
|
|
|
|
|
if grep (/^$indent\s/, @lines); |
519
|
0
|
|
|
|
|
|
my (@t) = split(/\n/, $self->text); |
520
|
0
|
|
|
|
|
|
my (%t); |
521
|
0
|
|
|
|
|
|
@t{strim(@t)} = @t; |
522
|
0
|
|
|
|
|
|
while ( @lines ) { |
523
|
0
|
|
|
|
|
|
my $l = strim(shift(@lines)); |
524
|
0
|
0
|
|
|
|
|
if ( $t{$l} ) { |
525
|
0
|
|
|
|
|
|
delete $t{$l}; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
else { |
528
|
0
|
|
|
|
|
|
push(@o, "$indent$l"); |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
} |
531
|
0
|
|
|
|
|
|
for my $k ( keys %t ) { |
532
|
0
|
|
|
|
|
|
unshift(@o, iinvert($indent, $k)); |
533
|
|
|
|
|
|
|
} |
534
|
0
|
0
|
|
|
|
|
unshift(@o, $self->setcontext) |
535
|
|
|
|
|
|
|
if @o; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
elsif ( $old->teql($desig) ) { |
539
|
0
|
0
|
|
|
|
|
print STDERR "DESIGNATOR EQUAL\n" if $debug_set; |
540
|
|
|
|
|
|
|
# okay |
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
else { |
543
|
0
|
0
|
|
|
|
|
print STDERR "DESIGNATOR DIFERENT\n" if $debug_set; |
544
|
0
|
|
|
|
|
|
push(@o, openangle($self->setcontext(@designators))); |
545
|
0
|
0
|
|
|
|
|
if ( defined $designator ) { |
546
|
0
|
|
|
|
|
|
push(@o, iinvert($indent, $designator)); |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
else { |
549
|
0
|
|
|
|
|
|
push(@o, iinvert($indent, split(/\n/, $self->text))); |
550
|
|
|
|
|
|
|
} |
551
|
0
|
|
|
|
|
|
push(@o, $desig); |
552
|
|
|
|
|
|
|
} |
553
|
0
|
0
|
|
|
|
|
if ( @lines ) { |
554
|
0
|
0
|
0
|
|
|
|
if ( $old && ! @o && $old->subs && $old->subs->next ) { |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
555
|
0
|
0
|
|
|
|
|
print STDERR "OLD= $old->{$debg}" if $debug_set; |
556
|
0
|
|
|
|
|
|
my $ok = 1; |
557
|
0
|
|
|
|
|
|
my $f = $old->subs->next; |
558
|
0
|
0
|
|
|
|
|
print STDERR "F= $f->{$debg}" if $debug_set; |
559
|
0
|
|
|
|
|
|
for my $l ( @lines ) { |
560
|
0
|
0
|
|
|
|
|
next if $l =~ /^\s*exit\s*$/; |
561
|
0
|
0
|
|
|
|
|
next if $f->teql($l); |
562
|
0
|
0
|
|
|
|
|
print STDERR "LINE DIFF ON $l\n" if $debug_set; |
563
|
0
|
|
|
|
|
|
$ok = 0; |
564
|
0
|
|
|
|
|
|
last; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
continue { |
567
|
0
|
|
|
|
|
|
$f = $f->next; |
568
|
0
|
0
|
|
|
|
|
print STDERR "F= $f->{$debg}" if $debug_set; |
569
|
|
|
|
|
|
|
} |
570
|
0
|
0
|
0
|
|
|
|
if ( ! $ok || $f ) { |
571
|
0
|
|
|
|
|
|
push(@o, openangle($self->setcontext(@designators))); |
572
|
0
|
|
|
|
|
|
push(@o, iinvert($indent, $designator)); |
573
|
0
|
|
|
|
|
|
push(@o, $desig); |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
} |
576
|
0
|
0
|
|
|
|
|
push(@o, @lines) if @o; |
577
|
|
|
|
|
|
|
} |
578
|
0
|
|
|
|
|
|
@o = grep (defined, @o); |
579
|
0
|
0
|
|
|
|
|
push(@o, closeangle($self->unsetcontext(@designators))) |
580
|
|
|
|
|
|
|
if @o; |
581
|
0
|
0
|
|
|
|
|
return join('', returns(@o)) unless wantarray; |
582
|
0
|
|
|
|
|
|
return returns(@o); |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
sub looks_like_a_block { |
586
|
0
|
|
|
0
|
0
|
|
my ($first, @l) = @_; |
587
|
0
|
|
|
|
|
|
my $last = pop(@l); |
588
|
0
|
0
|
|
|
|
|
return 1 if ! defined $last; |
589
|
0
|
0
|
|
|
|
|
return 0 if grep (/^\S/, @l); |
590
|
0
|
0
|
|
|
|
|
return 0 if $first =~ /^\s/; |
591
|
0
|
0
|
|
|
|
|
return 0 if $last =~ /^\s/; |
592
|
0
|
|
|
|
|
|
return 1; |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
sub iinvert { |
596
|
0
|
|
|
0
|
0
|
|
my ($indent, @l) = @_; |
597
|
0
|
0
|
|
|
|
|
confess unless @l; |
598
|
0
|
|
|
|
|
|
for $_ ( @l ) { |
599
|
0
|
0
|
|
|
|
|
next unless defined; |
600
|
0
|
0
|
|
|
|
|
s/^\s*no /$indent/ or s/^\s*(\S)/${indent}no $1/ |
601
|
|
|
|
|
|
|
} |
602
|
0
|
0
|
|
|
|
|
return $l[0] unless wantarray; |
603
|
0
|
|
|
|
|
|
return @l; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub all { |
607
|
0
|
|
|
0
|
0
|
|
my ($self, $regex) = @_; |
608
|
0
|
|
|
|
|
|
$self = $self->zoom; |
609
|
0
|
0
|
0
|
|
|
|
return(map { $self->{$_} } $self->sortit(grep (/$regex/ && ! /$spec/o, keys %$self))) |
|
0
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
if $regex; |
611
|
0
|
|
|
|
|
|
return(map { $self->{$_} } $self->sortit(grep (! /$spec/o, keys %$self))); |
|
0
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub get { |
615
|
0
|
|
|
0
|
0
|
|
my ($self, @designators) = @_; |
616
|
0
|
0
|
0
|
|
|
|
return $self->mget(@designators) |
617
|
|
|
|
|
|
|
if wantarray && @designators > 1; |
618
|
|
|
|
|
|
|
|
619
|
0
|
0
|
|
|
|
|
print STDERR "\nGET <@designators> $self->{$debg}" if $debug_get; |
620
|
|
|
|
|
|
|
|
621
|
0
|
0
|
|
|
|
|
return $self unless $self; |
622
|
0
|
|
|
|
|
|
my $zoom = $self->zoom->subs; |
623
|
0
|
0
|
|
|
|
|
$self = $zoom if $zoom; |
624
|
|
|
|
|
|
|
|
625
|
0
|
0
|
|
|
|
|
print STDERR "\nZOOMSUB $self->{$debg}" if $debug_get; |
626
|
|
|
|
|
|
|
|
627
|
0
|
|
|
|
|
|
while ( @designators ) { |
628
|
0
|
|
|
|
|
|
my $designator = shift(@designators); |
629
|
|
|
|
|
|
|
# $self = $self->zoom; |
630
|
|
|
|
|
|
|
# $self = $self->single || $self; |
631
|
0
|
0
|
|
|
|
|
print STDERR "\nDESIGNATOR: $designator. ZOOMED: $self->{$debg}\n" |
632
|
|
|
|
|
|
|
if $debug_get; |
633
|
0
|
|
|
|
|
|
for my $d ( split(' ', $designator) ) { |
634
|
0
|
0
|
|
|
|
|
print STDERR "\nDO WE HAVE A: $d?\n" if $debug_get; |
635
|
0
|
0
|
|
|
|
|
return $undef unless $self->{$d}; |
636
|
0
|
|
|
|
|
|
$self = $self->{$d}; |
637
|
0
|
0
|
|
|
|
|
print STDERR "\nWE DO: $self->{$debg}\n" if $debug_get; |
638
|
|
|
|
|
|
|
} |
639
|
0
|
0
|
|
|
|
|
last unless @designators; |
640
|
0
|
0
|
|
|
|
|
if ( $self->single ) { |
641
|
0
|
|
|
|
|
|
$self = $self->subs; |
642
|
0
|
0
|
|
|
|
|
print STDERR "\nSINGLETON: $self->{$debg}\n" if $debug_get; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
else { |
645
|
0
|
0
|
|
|
|
|
print STDERR "\nNOT SINGLE\n" if $debug_get; |
646
|
0
|
|
|
|
|
|
return $undef; |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
} |
649
|
0
|
0
|
|
|
|
|
print STDERR "\nDONE\n" if $debug_get; |
650
|
0
|
0
|
|
|
|
|
if ( wantarray ) { |
651
|
0
|
|
|
|
|
|
$self = $self->zoom; |
652
|
0
|
|
|
|
|
|
my (@k) = $self->kids; |
653
|
0
|
0
|
|
|
|
|
return @k if @k; |
654
|
0
|
|
|
|
|
|
return $self; |
655
|
|
|
|
|
|
|
} |
656
|
0
|
|
|
|
|
|
return $self; |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
sub strim { |
660
|
0
|
|
|
0
|
0
|
|
my (@l) = @_; |
661
|
0
|
|
|
|
|
|
for $_ ( @l ) { |
662
|
0
|
|
|
|
|
|
s/^\s+//; |
663
|
0
|
|
|
|
|
|
s/\s+$//; |
664
|
0
|
|
|
|
|
|
s/\n$//; |
665
|
|
|
|
|
|
|
} |
666
|
0
|
0
|
|
|
|
|
return $l[0] unless wantarray; |
667
|
0
|
|
|
|
|
|
return @l; |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub trim { |
671
|
0
|
|
|
0
|
0
|
|
my (@l) = @_; |
672
|
0
|
|
|
|
|
|
for $_ ( @l ) { |
673
|
0
|
|
|
|
|
|
s/^\s+//; |
674
|
0
|
|
|
|
|
|
s/\s+$//; |
675
|
|
|
|
|
|
|
} |
676
|
0
|
0
|
|
|
|
|
return $l[0] unless wantarray; |
677
|
0
|
|
|
|
|
|
return @l; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub display { |
681
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
682
|
0
|
|
|
|
|
|
my @o; |
683
|
0
|
|
|
|
|
|
push(@o, $self->setcontext); |
684
|
|
|
|
|
|
|
push(@o, trim($self->single->{$text})) |
685
|
0
|
0
|
0
|
|
|
|
if $self->single && $self->single->{$text} |
|
|
|
0
|
|
|
|
|
686
|
|
|
|
|
|
|
&& $self->subs->undefined; |
687
|
0
|
0
|
|
|
|
|
push(@o, "! the whole enchalada") |
688
|
|
|
|
|
|
|
if $self->context->undefined; |
689
|
0
|
|
|
|
|
|
my (@r) = returns(openangle(@o)); |
690
|
0
|
0
|
|
|
|
|
return @r if wantarray; |
691
|
0
|
|
|
|
|
|
return join('', @r); |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
sub callerlevels { |
695
|
0
|
|
|
0
|
0
|
|
my $n = 1; |
696
|
0
|
|
|
|
|
|
1 while caller($n ++); |
697
|
0
|
|
|
|
|
|
return $n; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
sub mget { |
701
|
0
|
|
|
0
|
0
|
|
my ($self, @designators) = @_; |
702
|
|
|
|
|
|
|
|
703
|
0
|
|
|
|
|
|
my $cl = callerlevels; |
704
|
0
|
|
|
|
|
|
my @newset; |
705
|
0
|
0
|
|
|
|
|
if ( @designators > 1 ) { |
706
|
|
|
|
|
|
|
|
707
|
0
|
0
|
|
|
|
|
print STDERR "\nGET$cl $designators[0]----------\n" if $debug_mget; |
708
|
|
|
|
|
|
|
|
709
|
0
|
|
|
|
|
|
my (@set) = $self->get(shift @designators); |
710
|
0
|
|
|
|
|
|
for my $item ( @set ) { |
711
|
|
|
|
|
|
|
|
712
|
0
|
0
|
|
|
|
|
print STDERR "\nMGET$cl $item ----------\n" if $debug_mget; |
713
|
0
|
0
|
|
|
|
|
print STDERR "\nMGET$cl $item->{$debg}\n" if $debug_mget; |
714
|
|
|
|
|
|
|
|
715
|
0
|
|
|
|
|
|
my (@got) = $item->mget(@designators); |
716
|
|
|
|
|
|
|
|
717
|
0
|
0
|
|
|
|
|
print STDERR map { "\nRESULTS$cl: $_->{$debg}\n" } @got |
|
0
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
if $debug_mget; |
719
|
|
|
|
|
|
|
|
720
|
0
|
|
|
|
|
|
push(@newset, @got); |
721
|
|
|
|
|
|
|
} |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
else { |
724
|
|
|
|
|
|
|
|
725
|
0
|
0
|
|
|
|
|
print STDERR "\nxGET$cl $designators[0] -------\n" if $debug_mget; |
726
|
|
|
|
|
|
|
|
727
|
0
|
|
|
|
|
|
(@newset) = $self->get(shift @designators); |
728
|
|
|
|
|
|
|
|
729
|
0
|
0
|
|
|
|
|
print STDERR map { "\nxRESULTS$cl: $_->{$debg}\n" } @newset |
|
0
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
if $debug_mget; |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
} |
733
|
0
|
|
|
|
|
|
return @newset; |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
sub sortit { |
737
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
738
|
0
|
|
|
|
|
|
return sort { $self->{$a}->seqn cmp $self->{$b}->seqn } @_; |
|
0
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
} |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
1; |