| 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; |