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 |
require 5.001;
|
10 |
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 |
print "Switcher: Badly formed $name tag -".
|
240 |
" undefined $key parameter\n";
|
241 |
exit 1;
|
242 |
}
|
243 |
$$hashref{$key}=~s/["']//;
|
244 |
}
|
245 |
|