1 |
williamc |
1.1 |
# Switcher Module
|
2 |
|
|
#
|
3 |
|
|
# Look for elements given in input has in a string
|
4 |
|
|
# If found then call a routine name with the same name
|
5 |
|
|
# Implemented as an object to maintain state info between each line
|
6 |
|
|
# processed.
|
7 |
|
|
|
8 |
|
|
package Switcher;
|
9 |
williamc |
1.2 |
require 5.001;
|
10 |
williamc |
1.1 |
require Exporter;
|
11 |
|
|
use Carp;
|
12 |
|
|
@ISA = qw(Exporter);
|
13 |
|
|
|
14 |
|
|
sub new {
|
15 |
|
|
my $class=shift;
|
16 |
|
|
my $hash=shift;
|
17 |
|
|
my $file=shift;
|
18 |
|
|
my $self = {};
|
19 |
|
|
bless $self, $class;
|
20 |
|
|
$self->_initialise($hash,$file);
|
21 |
|
|
return $self;
|
22 |
|
|
}
|
23 |
|
|
|
24 |
|
|
sub _initialise (hash1) {
|
25 |
|
|
my $self=shift;
|
26 |
|
|
my $inlabelhash=shift;
|
27 |
|
|
my $newkey;
|
28 |
|
|
my $key;
|
29 |
|
|
$self->{filename}=shift;
|
30 |
|
|
$self->{labelhash}={};
|
31 |
|
|
$self->{Strict_no_cr}='yes'; # set to 'no' to retain \n's
|
32 |
|
|
|
33 |
|
|
# setup SGML type tag definitions
|
34 |
|
|
# Others may be added without problems but ensure to provide
|
35 |
|
|
# a closure with a hash value of the correct type
|
36 |
|
|
# No capitals thanks.
|
37 |
|
|
%{$self->{opencontext}}=(
|
38 |
|
|
'<' => 'starttag',
|
39 |
|
|
'</' => 'endtag'
|
40 |
|
|
);
|
41 |
|
|
%{$self->{closecontext}}= (
|
42 |
|
|
">" => 'tag'
|
43 |
|
|
);
|
44 |
|
|
|
45 |
|
|
# Fill in the blanks in the user supplied hash
|
46 |
|
|
if ( ! ( defined $$inlabelhash{'none'} )) { # check for none target
|
47 |
|
|
$$inlabelhash{'none'}='none';
|
48 |
|
|
}
|
49 |
|
|
block1: foreach $key ( keys %$inlabelhash ) {
|
50 |
|
|
($newkey=$key)=~tr[A-Z][a-z];
|
51 |
|
|
${$self->{labelhash}}{$newkey}=$$inlabelhash{$key};
|
52 |
|
|
foreach $context ( values %{$self->{opencontext}} ) {
|
53 |
|
|
next block1 if $newkey=~/$context/i;
|
54 |
|
|
}
|
55 |
|
|
foreach $context ( values %{$self->{opencontext}} ) {
|
56 |
|
|
if ( defined ${$self->{labelhash}}{$newkey."_".$context} ) {
|
57 |
|
|
next block1;
|
58 |
|
|
}
|
59 |
|
|
# print "Setting ".$newkey."_".$context." = 'none'\n";
|
60 |
|
|
${$self->{labelhash}}{$newkey."_".$context}='none';
|
61 |
|
|
}
|
62 |
|
|
}
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
foreach $key ( %$self->{labelhash} ) {
|
66 |
|
|
${$self->{ContextHash}}{$key} = 0;
|
67 |
|
|
}
|
68 |
|
|
$self->{InTag}="none";
|
69 |
|
|
$taglabel="";
|
70 |
|
|
$self->{tagblock}=[];
|
71 |
|
|
@{$self->{lastcon}}= qw(none);
|
72 |
|
|
}
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
sub parse {
|
76 |
|
|
my $self=shift;
|
77 |
|
|
my $mykey="";
|
78 |
|
|
my $key;
|
79 |
|
|
my $word;
|
80 |
|
|
my $filein="";
|
81 |
|
|
$self->{linecount}=0;
|
82 |
|
|
use FileHandle;
|
83 |
|
|
my $filehandle=FileHandle->new();
|
84 |
|
|
open( $filehandle , "$self->{filename}" )
|
85 |
|
|
or carp "Switcher: Cannot open $self->{filename} $! \n";
|
86 |
|
|
while ( <$filehandle> ) {
|
87 |
|
|
if ( $self->{Strict_no_cr} eq 'yes' ) {
|
88 |
|
|
chomp;
|
89 |
|
|
}
|
90 |
|
|
@{$self->{words}}=split /\b/;
|
91 |
|
|
$self->{linecount}++;
|
92 |
|
|
WHILELOOP: while ( ($word=shift @{$self->{words}}) ne "" ) {
|
93 |
|
|
# print $word." --- Word\n";
|
94 |
|
|
if ( $word=~/(>)(<.*)/ ) {
|
95 |
|
|
unshift @{$self->{words}}, $2;
|
96 |
|
|
$word=$1;
|
97 |
|
|
}
|
98 |
|
|
#test against opencontext
|
99 |
|
|
foreach $mykey ( keys ( %{$self->{opencontext}}) ) {
|
100 |
|
|
if ( $word=~/$mykey/i ) {
|
101 |
|
|
# Send current tagblock (if its not empty)
|
102 |
|
|
# to the Lastest Context Routine
|
103 |
|
|
$self->_closeprevious();
|
104 |
|
|
# Now carry on the parse
|
105 |
|
|
$self->{InTag}=${$self->{opencontext}}{$mykey};
|
106 |
|
|
$#{$self->{tagblock}}=-1;
|
107 |
|
|
next WHILELOOP;
|
108 |
|
|
}
|
109 |
|
|
}
|
110 |
|
|
#test against closed context
|
111 |
|
|
foreach $key ( keys %{$self->{closecontext}} ) {
|
112 |
|
|
if ( $word=~/$key/i ) {
|
113 |
|
|
if ( $self->{InTag}=~/${$self->{closecontext}}{$key}/ ) {
|
114 |
|
|
$temp=(shift @{$self->{tagblock}});
|
115 |
|
|
$temp=~tr[A-Z][a-z];
|
116 |
|
|
$rtname=($temp)."_".$self->{InTag};
|
117 |
|
|
$self->{InTag}="none";
|
118 |
|
|
# Do we call the tag init routine?
|
119 |
|
|
if ( ( defined ( ${$self->{labelhash}}{$rtname} )) &&
|
120 |
|
|
( ! ( ${$self->{labelhash}}{$rtname}=~/none/i )) ) {
|
121 |
|
|
&{${$self->{labelhash}}{$rtname}}( $temp,
|
122 |
|
|
@{$self->{tagblock}});
|
123 |
|
|
}
|
124 |
|
|
$self->_flipcontext($temp);
|
125 |
|
|
$#{$self->{tagblock}}= -1;
|
126 |
|
|
next WHILELOOP;
|
127 |
|
|
}
|
128 |
|
|
else {
|
129 |
|
|
die "Unmatched \"$key\" on line $self->{linecount}"
|
130 |
|
|
if $self->{InTag} eq "none";
|
131 |
|
|
die "Error: Wrong closure \"$key\" on line $self->{linecount}";
|
132 |
|
|
}
|
133 |
|
|
}
|
134 |
|
|
}
|
135 |
|
|
push @{$self->{tagblock}}, $word;
|
136 |
|
|
} #end word while
|
137 |
|
|
} #end fileglob while
|
138 |
|
|
$self->_closeprevious();
|
139 |
|
|
close $filehandle;
|
140 |
|
|
}
|
141 |
|
|
|
142 |
|
|
sub context ($key) {
|
143 |
|
|
my $self=shift;
|
144 |
|
|
my $key=shift;
|
145 |
|
|
$key=~tr[A-Z][a-z];
|
146 |
|
|
return ( ${$self->{ContextHash}}{$key} );
|
147 |
|
|
}
|
148 |
|
|
|
149 |
|
|
|
150 |
|
|
# convert array of value=constants to a hash
|
151 |
|
|
# returns reference to the array
|
152 |
|
|
sub SetupValueHash(reftoarray) {
|
153 |
|
|
my $self=shift;
|
154 |
|
|
my $arrayref=shift;
|
155 |
|
|
my $side="r";
|
156 |
|
|
my $key='';
|
157 |
|
|
my $thiskey;
|
158 |
|
|
my $wordto="";
|
159 |
|
|
my $word;
|
160 |
|
|
my $quotes=0;
|
161 |
|
|
local $varhash;
|
162 |
|
|
|
163 |
|
|
$varhash = {};
|
164 |
|
|
foreach $word ( @$arrayref ) {
|
165 |
|
|
chomp;
|
166 |
|
|
if ( $word=~/=/) {
|
167 |
|
|
$side="l";
|
168 |
|
|
if ( $word=~s/^=// ) {
|
169 |
|
|
unshift @$arrayref, $word;
|
170 |
|
|
}
|
171 |
|
|
if ( $word=~s/^.*=// ) {
|
172 |
|
|
($thiskey=$word)=~tr[A-Z][a-z]; #keys all lower case
|
173 |
|
|
$key=$key.$thiskey;
|
174 |
|
|
}
|
175 |
|
|
next;
|
176 |
|
|
}
|
177 |
|
|
if ( $word=~/\"/ ) {
|
178 |
|
|
$quotes= ( ! $quotes);
|
179 |
|
|
if ( $word=~s/^"// ) {
|
180 |
|
|
unshift @$arrayref, $word;
|
181 |
|
|
}
|
182 |
|
|
next;
|
183 |
|
|
}
|
184 |
|
|
if ( ( $word=~/\s/ ) && ( ! $quotes) ) {
|
185 |
|
|
$side="r";
|
186 |
|
|
if ( $key=~/./) {
|
187 |
|
|
$$varhash{$key}=$wordto;
|
188 |
|
|
}
|
189 |
|
|
$key='';
|
190 |
|
|
$wordto="";
|
191 |
|
|
next;
|
192 |
|
|
}
|
193 |
|
|
if ( $side=~/r/) {
|
194 |
|
|
($thiskey=$word)=~tr[A-Z][a-z]; #keys all lower case
|
195 |
|
|
$key=$key.$thiskey;
|
196 |
|
|
}
|
197 |
|
|
else {
|
198 |
|
|
$wordto=$wordto.$word;
|
199 |
|
|
}
|
200 |
|
|
}
|
201 |
|
|
if ( $side=~/l/ ) { $$varhash{$key}=$wordto; }
|
202 |
|
|
return $varhash;
|
203 |
|
|
}
|
204 |
|
|
|
205 |
|
|
sub _flipcontext(Hashkey) {
|
206 |
|
|
my $self=shift;
|
207 |
|
|
my $key = shift;
|
208 |
|
|
${$self->{ContextHash}}{$key}=(! ${$self->{ContextHash}}{$key});
|
209 |
|
|
# sort out the context stack
|
210 |
|
|
if ( ! ${$self->{ContextHash}}{$key} ) {
|
211 |
|
|
pop @{$self->{lastcon}};
|
212 |
|
|
# print "** poping ".$key."\n";
|
213 |
|
|
}
|
214 |
|
|
else {
|
215 |
|
|
# print "** pushing ".$key."\n";
|
216 |
|
|
push @{$self->{lastcon}}, $key;
|
217 |
|
|
}
|
218 |
|
|
}
|
219 |
|
|
sub _closeprevious {
|
220 |
|
|
my $self=shift;
|
221 |
|
|
if ( $#{$self->{tagblock}} != -1 ) {
|
222 |
|
|
if (( defined
|
223 |
|
|
${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]} ) &&
|
224 |
|
|
( ! ( ${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]}
|
225 |
|
|
=~/none/i )) ) {
|
226 |
|
|
&{ ${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]}}(
|
227 |
|
|
${$self->{lastcon}}[$#{$self->{lastcon}}], @{$self->{tagblock}});
|
228 |
|
|
}
|
229 |
|
|
}
|
230 |
|
|
}
|
231 |
|
|
|
232 |
|
|
sub checkparam($hash, $name, $key) {
|
233 |
|
|
my $self=shift;
|
234 |
|
|
my $hashref=shift;
|
235 |
|
|
my $name=shift;
|
236 |
|
|
my $key=shift;
|
237 |
|
|
|
238 |
|
|
if ( ! defined $$hashref{$key} ) {
|
239 |
williamc |
1.3 |
print "Switcher: Badly formed $name tag -".
|
240 |
williamc |
1.1 |
" undefined $key parameter\n";
|
241 |
|
|
exit 1;
|
242 |
|
|
}
|
243 |
|
|
$$hashref{$key}=~s/["']//;
|
244 |
|
|
}
|
245 |
|
|
|