|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Config::IOD::Reader;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $DATE = '2021-06-23'; # DATE  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.343'; # VERSION  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
57104
 | 
 use 5.010001;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
    | 
| 
7
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
13
 | 
 use strict;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
    | 
| 
8
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
11
 | 
 use warnings;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
88
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
1139
 | 
 use parent qw(Config::IOD::Base);  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
798
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _merge {  | 
| 
13
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
12
 | 
     my ($self, $section) = @_;  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $res = $self->{_res};  | 
| 
16
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     for my $msect (@{ $self->{_merge} }) {  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
17
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         if ($msect eq $section) {  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # ignore merging self  | 
| 
19
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             next;  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #local $self->{_linum} = $self->{_linum}-1;  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #$self->_err("Can't merge section '$msect' to '$section': ".  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #                "Same section");  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
24
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
         if (!exists($res->{$msect})) {  | 
| 
25
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             local $self->{_linum} = $self->{_linum}-1;  | 
| 
26
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->_err("Can't merge section '$msect' to '$section': ".  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             "Section '$msect' not seen yet");  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
29
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
         for my $k (keys %{ $res->{$msect} }) {  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
30
 | 
14
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
56
 | 
             $res->{$section}{$k} //= $res->{$msect}{$k};  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _init_read {  | 
| 
36
 | 
64
 | 
 
 | 
 
 | 
  
64
  
 | 
 
 | 
89
 | 
     my $self = shift;  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
38
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
184
 | 
     $self->SUPER::_init_read;  | 
| 
39
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
219
 | 
     $self->{_res} = {};  | 
| 
40
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
     $self->{_merge} = undef;  | 
| 
41
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
107
 | 
     $self->{_num_seen_section_lines} = 0;  | 
| 
42
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
98
 | 
     $self->{_cur_section} = $self->{default_section};  | 
| 
43
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
133
 | 
     $self->{_arrayified} = {};  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _read_string {  | 
| 
47
 | 
68
 | 
 
 | 
 
 | 
  
68
  
 | 
 
 | 
139
 | 
     my ($self, $str, $cb) = @_;  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
49
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
103
 | 
     my $res = $self->{_res};  | 
| 
50
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
106
 | 
     my $cur_section = $self->{_cur_section};  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $directive_re = $self->{allow_bang_only} ?  | 
| 
53
 | 
68
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
293
 | 
         qr/^;?\s*!\s*(\w+)\s*/ :  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         qr/^;\s*!\s*(\w+)\s*/;  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
93
 | 
     my $_raw_val; # only to provide to callback  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
319
 | 
     my @lines = split /^/, $str;  | 
| 
59
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
     local $self->{_linum} = 0;  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   LINE:  | 
| 
61
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
131
 | 
     for my $line (@lines) {  | 
| 
62
 | 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
779
 | 
         $self->{_linum}++;  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # blank line  | 
| 
65
 | 
699
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1472
 | 
         if ($line !~ /\S/) {  | 
| 
66
 | 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
216
 | 
             next LINE;  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # directive line  | 
| 
70
 | 
518
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
2618
 | 
         if ($self->{enable_directive} && $line =~ s/$directive_re//) {  | 
| 
71
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
             my $directive = $1;  | 
| 
72
 | 
25
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
55
 | 
             if ($self->{allow_directives}) {  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $self->_err("Directive '$directive' is not in ".  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                 "allow_directives list")  | 
| 
75
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
                     unless grep { $_ eq $directive }  | 
| 
76
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                         @{$self->{allow_directives}};  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
78
 | 
24
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
42
 | 
             if ($self->{disallow_directives}) {  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $self->_err("Directive '$directive' is in ".  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                 "disallow_directives list")  | 
| 
81
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
                     if grep { $_ eq $directive }  | 
| 
82
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                         @{$self->{disallow_directives}};  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
84
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
             my $args = $self->_parse_command_line($line);  | 
| 
85
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
             if (!defined($args)) {  | 
| 
86
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
                 $self->_err("Invalid arguments syntax '$line'");  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
89
 | 
21
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
33
 | 
             if ($cb) {  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $cb->(  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     event => 'directive',  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     linum=>$self->{_linum}, line=>$line, cur_section=>$self->{_cur_section},  | 
| 
93
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     directive => $directive,  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     args => $args,  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 );  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
21
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
58
 | 
             if ($directive eq 'include') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                 my $path;  | 
| 
100
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
                 if (! @$args) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
                     $self->_err("Missing filename to include");  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif (@$args > 1) {  | 
| 
103
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $self->_err("Extraneous arguments");  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
105
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                     $path = $args->[0];  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
107
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                 my $res = $self->_push_include_stack($path);  | 
| 
108
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
26
 | 
                 if ($res->[0] != 200) {  | 
| 
109
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                     $self->_err("Can't include '$path': $res->[1]");  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
111
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                 $path = $res->[2];  | 
| 
112
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
                 $self->_read_string($self->_read_file($path, $cb), $cb);  | 
| 
113
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
                 $self->_pop_include_stack;  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif ($directive eq 'merge') {  | 
| 
115
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
                 $self->{_merge} = @$args ? $args : undef;  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif ($directive eq 'noop') {  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
118
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                 if ($self->{ignore_unknown_directive}) {  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     # assume a regular comment  | 
| 
120
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
                     next LINE;  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
122
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                     $self->_err("Unknown directive '$directive'");  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
125
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
             next LINE;  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # comment line  | 
| 
129
 | 
493
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1118
 | 
         if ($line =~ /^\s*[;#]/) {  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
131
 | 
64
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
111
 | 
             if ($cb) {  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $cb->(  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     event => 'comment',  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     linum=>$self->{_linum}, line=>$line, cur_section=>$self->{_cur_section},  | 
| 
135
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 );  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
138
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
89
 | 
             next LINE;  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # section line  | 
| 
142
 | 
429
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
859
 | 
         if ($line =~ /^\s*\[\s*(.+?)\s*\](?: \s*[;#].*)?/) {  | 
| 
143
 | 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
             my $prev_section = $self->{_cur_section};  | 
| 
144
 | 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
175
 | 
             $self->{_cur_section} = $cur_section = $1;  | 
| 
145
 | 
72
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
336
 | 
             $res->{$cur_section} //= {};  | 
| 
146
 | 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
100
 | 
             $self->{_num_seen_section_lines}++;  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # previous section exists? do merging for previous section  | 
| 
149
 | 
72
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
155
 | 
             if ($self->{_merge} && $self->{_num_seen_section_lines} > 1) {  | 
| 
150
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
                 $self->_merge($prev_section);  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
153
 | 
72
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
113
 | 
             if ($cb) {  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $cb->(  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     event => 'section',  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     linum=>$self->{_linum}, line=>$line, cur_section=>$self->{_cur_section},  | 
| 
157
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     section => $cur_section,  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 );  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
130
 | 
             next LINE;  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # key line  | 
| 
165
 | 
357
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1170
 | 
         if ($line =~ /^\s*([^=]+?)\s*=\s*(.*)/) {  | 
| 
166
 | 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
568
 | 
             my $key = $1;  | 
| 
167
 | 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
487
 | 
             my $val = $2;  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # the common case is that value are not decoded or  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # quoted/bracketed/braced, so we avoid calling _parse_raw_value here  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # to avoid overhead  | 
| 
172
 | 
352
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
570
 | 
             if ($val =~ /\A["!\\[\{~]/) {  | 
| 
173
 | 
66
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
131
 | 
                 $_raw_val = $val if $cb;  | 
| 
174
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
179
 | 
                 my ($err, $parse_res, $decoded_val) = $self->_parse_raw_value($val);  | 
| 
175
 | 
66
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
149
 | 
                 $self->_err("Invalid value: " . $err) if $err;  | 
| 
176
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
                 $val = $decoded_val;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
178
 | 
286
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
410
 | 
                 $_raw_val = $val if $cb;  | 
| 
179
 | 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
530
 | 
                 $val =~ s/\s*[#;].*//; # strip comment  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
344
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
678
 | 
             if (exists $res->{$cur_section}{$key}) {  | 
| 
183
 | 
27
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
85
 | 
                 if (!$self->{allow_duplicate_key}) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
184
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                     $self->_err("Duplicate key: $key (section $cur_section)");  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($self->{_arrayified}{$cur_section}{$key}++) {  | 
| 
186
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
                     push @{ $res->{$cur_section}{$key} }, $val;  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
    | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     $res->{$cur_section}{$key} = [  | 
| 
189
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
                         $res->{$cur_section}{$key}, $val];  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
192
 | 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
623
 | 
                 $res->{$cur_section}{$key} = $val;  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
195
 | 
343
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
478
 | 
             if ($cb) {  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $cb->(  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     event => 'key',  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     linum=>$self->{_linum}, line=>$line, cur_section=>$self->{_cur_section},  | 
| 
199
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     key => $key,  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     val => $val,  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     raw_val => $_raw_val,  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 );  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
497
 | 
             next LINE;  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
208
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         $self->_err("Invalid syntax");  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
211
 | 
45
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
150
 | 
     if ($self->{_merge} && $self->{_num_seen_section_lines} > 1) {  | 
| 
212
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         $self->_merge($cur_section);  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
239
 | 
     $res;  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ABSTRACT: Read IOD/INI configuration files  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |