File Coverage

blib/lib/Config/Objective.pm
Criterion Covered Total %
statement 80 107 74.7
branch 11 20 55.0
condition n/a
subroutine 12 17 70.5
pod 4 5 80.0
total 107 149 71.8


line stmt bran cond sub pod time code
1              
2             ###
3             ### Copyright 2002-2003 University of Illinois Board of Trustees
4             ### Copyright 2002-2003 Mark D. Roth
5             ### All rights reserved.
6             ###
7             ### Config::Objective - Perl module for parsing object-oriented config files
8             ###
9             ### Mark D. Roth
10             ### Campus Information Technologies and Educational Services
11             ### University of Illinois at Urbana-Champaign
12             ###
13              
14              
15             package Config::Objective;
16              
17 1     1   7163 use 5.006;
  1         4  
  1         44  
18 1     1   6 use strict;
  1         2  
  1         36  
19 1     1   7 use warnings;
  1         6  
  1         42  
20             #use overload;
21              
22 1     1   2106 use Parse::Lex;
  1         25138  
  1         33  
23              
24 1     1   574 use Config::Objective::DataType;
  1         2  
  1         22  
25 1     1   512 use Config::Objective::Parser;
  1         3  
  1         1082  
26              
27              
28             our $VERSION = '0.9.1';
29             our $AUTOLOAD;
30              
31              
32             ###############################################################################
33             ### internal functions for use by parser
34             ###############################################################################
35              
36             sub _lexer
37             {
38 498     498   16762 my ($parser) = @_;
39 498         571 my ($token, $lexer);
40              
41 498         1192 $lexer = $parser->YYData->{'lexer'};
42             # print "lexer = $lexer\n";
43              
44 498         2905 while (1)
45             {
46 557         1641 $token = $lexer->next;
47              
48 557 100       66147 if ($lexer->eoi)
49             {
50             # print "lexer returning EOI\n";
51 1         10 return ('', undef);
52             }
53              
54             next
55 556 100       3373 if ($token->name eq 'COMMENT');
56              
57             # print "lexer returning (" . $token->name . ", \"" . $token->text . "\")\n";
58 497         2841 return ($token->name, $token->text);
59             }
60             }
61              
62              
63             sub _error
64             {
65 0     0   0 my ($parser) = @_;
66 0         0 my ($config, $lexer, $file, $line);
67              
68 0         0 $config = $parser->YYData->{'config'};
69 0         0 $file = $config->{'file_stack'}->[-1];
70              
71 0         0 $lexer = $parser->YYData->{'lexer'};
72 0         0 $line = $lexer->line;
73              
74 0         0 die("$file:$line: parse error\n");
75             }
76              
77              
78             sub _call_obj_method
79             {
80 63     63   129 my ($self, $obj, $method, @args) = @_;
81 63         66 my ($retval, $line, $msg);
82              
83             # print "==> _call_obj_method('$obj', '$method'";
84             # map { print ", '$_'"; } @args
85             # if (@args > 1 || defined($args[0]));
86             # print ")\n";
87              
88 63 50       193 die "$obj: unknown config object"
89             if (!exists($self->{'objs'}->{$obj}));
90              
91 63 50       119 $method = 'default'
92             if (!defined($method));
93              
94 63         75 $retval = eval { $self->{'objs'}->{$obj}->$method(@args); };
  63         344  
95 63 50       133 if ($@)
96             {
97 0 0       0 if (@{$self->{'lexer_stack'}})
  0         0  
98             {
99 0         0 $line = $self->{'lexer_stack'}->[-1]->line;
100 0         0 $msg = "$self->{'file_stack'}->[-1]:$line: ";
101             }
102 0         0 $msg .= "$obj";
103 0         0 die "$msg: $@";
104             }
105              
106             # print "<== _call_obj_method(): returning '"
107             # . (defined($retval) ? $retval : 'undef') . "'\n";
108 63         181 return $retval;
109             }
110              
111              
112             ###############################################################################
113             ### constructor
114             ###############################################################################
115              
116             sub new
117             {
118 1     1 1 3 my ($class, $file, $objs, %opts) = @_;
119 1         2 my ($self);
120              
121 1         3 $self = \%opts;
122 1         3 bless($self, $class);
123              
124 1         11 $self->{'objs'} = $objs;
125 1 50       5 $self->{'objs'} = {}
126             if (!defined($self->{'objs'}));
127              
128 1 50       7 $self->{'include_dir'} = '.'
129             if (!defined($self->{'include_dir'}));
130              
131 1         3 $self->{'file_stack'} = [];
132 1         3 $self->{'cond_stack'} = [];
133 1         2 $self->{'list_stack'} = [];
134 1         3 $self->{'hash_stack'} = [];
135              
136 1         3 $self->{'in_expr'} = 0;
137              
138 1         4 $self->parse($file);
139              
140 1         6 return $self;
141             }
142              
143              
144             ###############################################################################
145             ### config parser
146             ###############################################################################
147              
148             sub parse
149             {
150 1     1 0 2 my ($self, $file) = @_;
151 1         2 my ($fh, $lexer, $parser);
152              
153             # print "==> parse('$file')\n";
154              
155 1 50       40 open($fh, $file)
156             || die "open($file): $!\n";
157 1         2 push(@{$self->{'file_stack'}}, $file);
  1         4  
158              
159             $lexer = Parse::Lex->new(
160             'AND', '&&',
161             'COMMA', ',',
162             'COMMENT', '(?
163             'ELIF', '^\%[ \t]*elif',
164             'ELSE', '^\%[ \t]*else',
165             'ENDIF', '^\%[ \t]*endif',
166             'EOS', ';',
167             'PAREN_START', '\(',
168             'PAREN_END', '\)',
169             'HASH_ARROW', '=>',
170             'HASH_START', '{',
171             'HASH_END', '}',
172             'IF', '^\%[ \t]*if',
173             'INCLUDE', '^\%[ \t]*include',
174             'LIST_START', '\[',
175             'LIST_END', '\]',
176             'METHOD_ARROW', '->',
177             'NOT', '!',
178             'OR', '\|\|',
179             'WORD', '\w+',
180             'QSTRING', [
181             '(?
182             '([^"]|(?<=\\\\)")*',
183             '(?
184             ],
185             sub {
186 12     12   963 my ($token, $string) = @_;
187              
188 12         42 $string =~ s/^"//;
189 12         37 $string =~ s/"$//;
190              
191 12         16 $string =~ s/\\"/"/g;
192              
193 12         231 return $string;
194             },
195             'ERROR', '(?s:.*)',
196             sub {
197 0     0   0 my $line = $_[0]->lexer->line;
198 0         0 my $file = $self->{'file_stack'}->[-1];
199              
200 0         0 die "$file:$line: syntax error: \"$_[1]\"\n";
201             }
202 1         28 );
203 1         2054 $lexer->from(\*$fh);
204 1         21978 $lexer->configure('Skip' => '\s+');
205 1         142 push(@{$self->{'lexer_stack'}}, $lexer);
  1         8  
206              
207 1         24 $parser = Config::Objective::Parser->new();
208 1         11 $parser->YYData->{'lexer'} = $lexer;
209 1         18 $parser->YYData->{'config'} = $self;
210              
211 1         15 $parser->YYParse(yylex => \&_lexer,
212             # yydebug => 0x1F,
213             yyerror => \&_error);
214              
215 1         56 pop(@{$self->{'file_stack'}});
  1         5  
216 1         3 pop(@{$self->{'lexer_stack'}});
  1         4  
217 1         39 close($fh);
218              
219             # print "<== parse('$file')\n";
220              
221 1         156 return 1;
222             }
223              
224              
225             ###############################################################################
226             ### allow direct access to object values
227             ###############################################################################
228              
229             sub AUTOLOAD
230             {
231 21     21   464 my ($self) = @_;
232 21         22 my ($method);
233              
234 21         25 $method = $AUTOLOAD;
235 21         68 $method =~ s/.*:://;
236              
237             return
238 21 50       47 if ($method eq 'DESTROY');
239              
240             # return (overload::Overloaded($self->{'objs'}->{$method})
241             # ? $self->{'objs'}->{$method}
242             # : $self->{'objs'}->{$method}->get());
243              
244 21         102 return $self->{'objs'}->{$method}->get();
245             }
246              
247              
248             ###############################################################################
249             ### return a config object
250             ###############################################################################
251              
252             sub get_obj
253             {
254 0     0 1   my ($self, $obj) = @_;
255              
256 0           return $self->{'objs'}->{$obj};
257             }
258              
259              
260             ###############################################################################
261             ### get a list of config object names
262             ###############################################################################
263              
264             sub obj_names
265             {
266 0     0 1   my ($self) = @_;
267              
268 0           return keys %{$self->{'objs'}};
  0            
269             }
270              
271              
272             ###############################################################################
273             ### get a hash of object names and values
274             ###############################################################################
275              
276             sub get_hash
277             {
278 0     0 1   my ($self) = @_;
279 0           my ($href);
280              
281 0           $href = {};
282 0           map { $href->{$_} = $self->$_; } $self->obj_names();
  0            
283              
284 0           return $href;
285             }
286              
287              
288             ###############################################################################
289             ### cleanup and documentation
290             ###############################################################################
291              
292             1;
293              
294             __END__