aboutsummaryrefslogtreecommitdiff
path: root/lib/Config/Parser.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Config/Parser.pm')
-rw-r--r--lib/Config/Parser.pm116
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/Config/Parser.pm b/lib/Config/Parser.pm
new file mode 100644
index 0000000..c0a2179
--- /dev/null
+++ b/lib/Config/Parser.pm
@@ -0,0 +1,116 @@
1package Config::Parser;
2use strict;
3use warnings;
4use parent 'Config::Tree';
5use Carp;
6use Cwd qw(abs_path);
7use Text::ParseWords;
8use Class::Inspector;
9
10our $VERSION = "1.00";
11
12sub new {
13 my $class = shift;
14 local %_ = @_;
15
16 my @parseargs;
17 if (my $filename = delete $_{filename}) {
18 push @parseargs, $filename;
19 foreach my $k (qw(fh line)) {
20 if (my $v = delete $_{$k}) {
21 push @parseargs, ($k, $v);
22 }
23 }
24 }
25
26 unless ($_{parameters}) {
27 my $subs = Class::Inspector->subclasses(__PACKAGE__);
28 if ($subs) {
29 $_{parameters} = {};
30 foreach my $c (@$subs) {
31# print "LOADING FROM $c\n";
32 if (my $s = loadsynt($c)) {
33 $_{parameters} = { %{$_{parameters}}, %$s };
34 }
35 last if $c eq $class;
36 }
37 delete $_{parameters} unless keys %{$_{parameters}};
38 }
39 }
40
41 my $self = $class->SUPER::new(%_);
42
43 if (@parseargs) {
44 $self->parse(@parseargs);
45 $self->commit or croak "configuration failed";
46 }
47
48 return $self;
49}
50
51sub findsynt {
52 my $class = shift;
53 my $file = $class;
54 $file =~ s{::}{/}g;
55 $file .= '.pm';
56 $file = abs_path($INC{$file})
57 or croak "can't find module file for $class";
58 local ($/, *FILE);
59 open FILE, $file or croak "Can't open $file";
60 my ($text, $data) = split /(?m)^__DATA__$/, <FILE>, 2;
61 close FILE;
62
63 return () unless $data;
64 return ($file, 1+($text =~ tr/\n//), $data);
65}
66
67sub loadsynt {
68 my ($class) = @_;
69 if (my ($file, $line, $data) = findsynt($class)) {
70 open(my $fh, '<', \$data);
71 my $d = $class->new(filename => $file,
72 fh => $fh,
73 line => $line,
74 parameters => { '*' => '*' })
75 or croak "Failed to parse template at $file:$line";
76 close $fh;
77 $d->as_hash(sub {
78 my ($what, $name, $val) = @_;
79 $name = '*' if $name eq 'ANY';
80 if ($what eq 'section') {
81 $val->{section} = {};
82 if ($name =~ s/:mandatory$//) {
83 $val->{mandatory} = 1;
84 }
85 ($name, $val->{section});
86 } else {
87 my @words = parse_line('\s+', 0, $val);
88 my $ret = {};
89 $val = shift @words;
90
91 if ($val eq 'STRING') {
92 # nothing
93 } elsif ($val eq 'NUMBER') {
94 $ret->{re} = '\d+';
95 } elsif ($val eq 'OCTAL') {
96 $ret->{re} = '[0-7]+';
97 } elsif ($val eq 'HEX') {
98 $ret->{re} = '([0-9][A-Fa-f])+';
99 } else {
100 unshift @words, $val;
101 }
102
103 while (($val = shift @words)
104 && $val =~ /^:(?<kw>.+?)(?:\s*=\s*(?<val>.*))?$/) {
105 $ret->{$+{kw}} = $+{val} // 1;
106 }
107 $ret->{default} = $val if $val;
108 ($name, $ret);
109 }
110 })->{section};
111 }
112}
113
1141;
115
116

Return to:

Send suggestions and report system problems to the System administrator.