6 |
|
# processed. |
7 |
|
# Interface |
8 |
|
# --------- |
9 |
+ |
# |
10 |
|
# new(file,objectref) : A new object - filename of file to parse |
11 |
< |
# objectref->of the methods |
11 |
> |
# objectref->of the methods |
12 |
|
# usetags(tagobjref) : Specify a tagcontainer set to direct to |
13 |
|
# to the desired routines |
14 |
|
# usegroupchecker(groupchecker) : Set a groupchecker |
15 |
|
# parse() : Parse the file |
16 |
< |
# checkparam($name,$par) : Exit with an error message if parameter |
17 |
< |
# is undefined in tag $name |
18 |
< |
# line() : return the current line number of the parse |
19 |
< |
|
16 |
> |
# line() : return the current line number of the parse |
17 |
> |
# tagstartline() : return the line number on which the current |
18 |
> |
# tag was opened |
19 |
> |
# stream(filehandle) : stream output to the filehandle if not handled |
20 |
> |
# in any other way |
21 |
|
package ActiveDoc::Switcher; |
22 |
+ |
use Utilities::Verbose; |
23 |
|
require 5.001; |
24 |
|
use Carp; |
25 |
|
|
26 |
+ |
@ISA=qw(Utilities::Verbose); |
27 |
+ |
|
28 |
|
sub new { |
29 |
|
my $class=shift; |
30 |
|
my $file=shift; |
31 |
|
my $objectname=shift; |
32 |
|
my $groupchecker=shift; |
33 |
|
|
34 |
< |
my $self = {}; |
34 |
> |
$self = {}; |
35 |
|
$self->{allw}=$objectname; |
36 |
|
bless $self, $class; |
37 |
|
$self->_initialise($file); |
38 |
|
return $self; |
39 |
|
} |
40 |
|
|
41 |
< |
sub _initialise (hash1) { |
41 |
> |
sub stream { |
42 |
> |
my $self=shift; |
43 |
> |
|
44 |
> |
$self->{stream}=shift; |
45 |
> |
} |
46 |
> |
|
47 |
> |
sub streamexclude { |
48 |
|
my $self=shift; |
49 |
< |
$self->{filename}=shift; |
49 |
> |
my $tag=shift; |
50 |
|
|
51 |
< |
# add a default groupchecker |
52 |
< |
use ActiveDoc::GroupChecker; |
42 |
< |
$self->{groupchecker}=GroupChecker->new(); |
43 |
< |
$self->{groupchecker}->include("all"); |
44 |
< |
|
45 |
< |
# Add a default TagContainer |
46 |
< |
use ActiveDoc::TagContainer; |
47 |
< |
$self->{tagcontainer}=ActiveDoc::TagContainer->new(); |
48 |
< |
|
51 |
> |
$tag=~tr/A-Z/a-z/; |
52 |
> |
$self->{streamexclude}{$tag}=1; |
53 |
|
} |
54 |
|
|
55 |
+ |
sub _initialise (hash1) |
56 |
+ |
{ |
57 |
+ |
my $self=shift; |
58 |
+ |
$self->{filename}=shift; |
59 |
+ |
$self->verbose(">> New ActiveDoc::Switcher created."); |
60 |
+ |
# add a default groupchecker |
61 |
+ |
use ActiveDoc::GroupChecker; |
62 |
+ |
$self->{groupchecker}=GroupChecker->new(); |
63 |
+ |
$self->{groupchecker}->include("all"); |
64 |
+ |
|
65 |
+ |
# Add a default TagContainer |
66 |
+ |
use ActiveDoc::TagContainer; |
67 |
+ |
$self->{tagcontainer}=ActiveDoc::TagContainer->new(); |
68 |
+ |
|
69 |
+ |
} |
70 |
+ |
|
71 |
|
sub usetags { |
72 |
|
my $self=shift; |
73 |
|
my $tagcontainer=shift; |
85 |
|
sub parse { |
86 |
|
my $self=shift; |
87 |
|
my $char; |
88 |
+ |
my $buf; |
89 |
|
$self->{linecount}=0; |
90 |
|
$self->_resetvars(); |
91 |
+ |
$self->{streamstore}=""; |
92 |
+ |
$self->{streamtmp}=""; |
93 |
|
|
94 |
|
# Open the file |
95 |
|
use FileHandle; |
96 |
< |
my $filehandle=FileHandle->new(); |
97 |
< |
open( $filehandle , "$self->{filename}" ) |
96 |
> |
local $filehandle; |
97 |
> |
$filehandle=FileHandle->new(); |
98 |
> |
|
99 |
> |
$self->verbose(">> Reading file: ".$self->{filename}." "); |
100 |
> |
|
101 |
> |
$filehandle->open("<".$self->{filename}) |
102 |
|
or return 1; |
103 |
< |
# or carp "Switcher: Cannot open $self->{filename} $! \n"; |
103 |
> |
# The buffering seems all messed up - best not to use it |
104 |
> |
$filehandle->setvbuf($buf, _IONBF, 3000); |
105 |
|
|
78 |
– |
print "Starting Parse $self->{filename}\n"; |
106 |
|
# Start file processing |
107 |
< |
while ( <$filehandle> ) { |
107 |
> |
while ( ($_=<$filehandle>) ) { |
108 |
> |
# Skip lines that start with a hash. A better way |
109 |
> |
# of adding comments than ignore tags: |
110 |
> |
next if (/^#/); |
111 |
|
$self->{linecount}++; |
112 |
|
$self->{currentline}=$_; |
113 |
|
$self->{stringpos}=0; |
115 |
|
$self->_checkchar($char); |
116 |
|
} # end char while |
117 |
|
} # End String while loop |
118 |
< |
close $filehandle; |
119 |
< |
print "Exiting Parse $self->{filename}\n"; |
120 |
< |
} |
121 |
< |
|
92 |
< |
sub checkparam($name, $key) { |
93 |
< |
my $self=shift; |
94 |
< |
my $name=shift; |
95 |
< |
my $key=shift; |
96 |
< |
|
97 |
< |
if ( ! defined $self->{tagvar}{$key} ) { |
98 |
< |
print "Switcher: Badly formed $name tag -". |
99 |
< |
" undefined $key parameter\n"; |
100 |
< |
exit 1; |
101 |
< |
} |
118 |
> |
undef $filehandle; |
119 |
> |
# make sure we close the last buffer |
120 |
> |
$self->_calltag($self->{textcontext}, $self->{textcontext}, |
121 |
> |
$self->_getstore()); |
122 |
|
} |
123 |
|
|
124 |
|
# |
128 |
|
my $self=shift; |
129 |
|
return $self->{linecount}; |
130 |
|
} |
131 |
+ |
|
132 |
+ |
# return the line the current tag was opened |
133 |
+ |
sub tagstartline { |
134 |
+ |
my $self=shift; |
135 |
+ |
$self->{tagstart}; |
136 |
+ |
} |
137 |
|
# --------------- Utility routines ---------------------------- |
138 |
|
|
139 |
|
# |
156 |
|
my $char=shift; |
157 |
|
my $string; |
158 |
|
|
159 |
+ |
|
160 |
|
# ---- In a tag |
161 |
|
if ( $self->{tagcontext}=~/tag/ ) { |
162 |
+ |
$self->{tagbuff}=$self->{tagbuff}.$char; |
163 |
|
if ( ! $self->_quotetest($char) ) { |
164 |
|
if ( ! $self->_labeltest($char) ) { |
165 |
|
if ( $char eq ">") { $self->_closetag(); } |
182 |
|
my $self=shift; |
183 |
|
my $char; |
184 |
|
$char=substr($self->{currentline},$self->{stringpos}++,1); |
185 |
< |
# print "Debug : Fetching character $char\n"; |
185 |
> |
|
186 |
> |
# Keep a record for any stream processes |
187 |
> |
$self->{streamstore}=$self->{streamstore}.$char; |
188 |
> |
|
189 |
|
return $char; |
190 |
|
} |
191 |
|
|
193 |
|
my $self=shift; |
194 |
|
my $char; |
195 |
|
|
196 |
+ |
# Keep a record of where the tag started |
197 |
+ |
$self->{tagstart}=$self->line(); |
198 |
+ |
|
199 |
|
# Close the last text segment |
200 |
+ |
$self->{streamtmp}=$self->_popstream(); |
201 |
|
$self->_calltag($self->{textcontext}, $self->{textcontext}, |
202 |
|
$self->_getstore()); |
203 |
|
$self->_resetstore(); |
205 |
|
|
206 |
|
# Do we have an opening or closing tag? |
207 |
|
if ( ($char=$self->_nextchar()) eq "/" ) { #we have a closing tag |
208 |
+ |
$self->{tagbuff}="<".$char; |
209 |
|
$self->{tagcontext}="endtag"; |
210 |
|
} |
211 |
|
else { # an opening tag |
212 |
+ |
$self->{tagbuff}="<"; |
213 |
|
$self->{tagcontext}="starttag"; |
214 |
|
$self->_checkchar($char); |
215 |
|
} |
179 |
– |
#print "\nDebug : Opening $self->{tagcontext}\n"; |
216 |
|
} |
217 |
|
|
218 |
|
# |
226 |
|
$self->_closelabel(); |
227 |
|
|
228 |
|
# -- Call the associated tag function if appropriate |
229 |
< |
$tagroutine=$self->{tagname}."_".$self->{tagcontext}; |
230 |
< |
$self->_calltag($tagroutine, $self->{tagname}, |
229 |
> |
if ( defined $self->{tagname} ) { |
230 |
> |
$tagroutine=$self->{tagname}."_".$self->{tagcontext}; |
231 |
> |
$self->_calltag($tagroutine, $self->{tagname}, |
232 |
|
$self->{tagvar}); |
196 |
– |
#print "\nDebug : Closing Tag $tagroutine\n"; |
233 |
|
|
234 |
< |
# -- Now make sure the text context is set for calling routines to |
235 |
< |
# -- deal with text portions outside of tags |
236 |
< |
if ( $self->{tagcontext} eq "starttag" ) { |
237 |
< |
push @{$self->{textstack}} , $self->{textcontext}; |
238 |
< |
$self->{textcontext}=$self->{tagname}; |
239 |
< |
} |
240 |
< |
else { |
234 |
> |
# -- Now make sure the text context is set for calling routines to |
235 |
> |
# -- deal with text portions outside of tags |
236 |
> |
if ( ($self->{tagcontext} eq "starttag") ) { |
237 |
> |
if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) { |
238 |
> |
push @{$self->{textstack}} , $self->{textcontext}; |
239 |
> |
$self->{textcontext}=$self->{tagname}; |
240 |
> |
} |
241 |
> |
} |
242 |
> |
else { |
243 |
|
if ( $#{$self->{textstack}} > -1 ) { |
244 |
< |
if ( $self->{textcontext} eq $self->{tagname} ) { |
245 |
< |
$self->{textcontext}=pop @{$self->{textstack}}; |
246 |
< |
} |
244 |
> |
if ( $self->{textcontext} eq $self->{tagname} ) { |
245 |
> |
if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) { |
246 |
> |
# -- watch out for valid tags we ignore in this parse |
247 |
> |
$self->{textcontext}=pop @{$self->{textstack}}; |
248 |
> |
} |
249 |
> |
} |
250 |
|
else { #The tag we are closing is not the last one so |
251 |
|
# we keep our current context. |
252 |
|
$self->_removefromstack($self->{tagname},$self->{textstack}); |
254 |
|
|
255 |
|
} |
256 |
|
else { # more close tags than open ones |
257 |
+ |
if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) { |
258 |
|
print "Warning : Unmatched </...> tag on line ". |
259 |
|
$self->line()."\n"; |
260 |
+ |
} |
261 |
|
} |
262 |
+ |
} |
263 |
|
} |
264 |
|
# Reset context back to text |
265 |
|
$self->{tagcontext}="text"; |
270 |
|
my $tagroutine=shift; |
271 |
|
my @args=@_; |
272 |
|
my $rt; |
273 |
+ |
my $found=0; |
274 |
|
|
275 |
|
if ( $self->{groupchecker}->status() || |
276 |
|
( $self->{tagcontainer}->inquiregroup($tagroutine)) ) { |
277 |
< |
$rt=$self->{tagcontainer}->getroutine($tagroutine); |
277 |
> |
($rt,$obj)=$self->{tagcontainer}->getroutine($tagroutine); |
278 |
|
if ( $rt ne "" ) { |
279 |
+ |
if ( ! defined $obj ) { |
280 |
|
&{$rt}( $self->{allw},@_); |
281 |
+ |
} |
282 |
+ |
else { |
283 |
+ |
&{$rt}( $obj,@_); |
284 |
+ |
} |
285 |
+ |
$found=1; |
286 |
|
} |
287 |
|
} |
288 |
+ |
|
289 |
+ |
# stream function |
290 |
+ |
if ( ! exists $self->{streamexclude}{$tagroutine} ) { |
291 |
+ |
$self->_printstream(); |
292 |
+ |
} |
293 |
+ |
$self->_clearstream(); |
294 |
+ |
} |
295 |
+ |
|
296 |
+ |
sub _clearstream { |
297 |
+ |
my $self=shift; |
298 |
+ |
$self->{streamstore}=(($self->{streamtmp} ne "")?$self->{streamtmp}:""); |
299 |
+ |
$self->{streamtmp}=""; |
300 |
+ |
} |
301 |
+ |
|
302 |
+ |
sub _popstream { |
303 |
+ |
my $self=shift; |
304 |
+ |
$self->{streamstore}=~s/(.*)(.)$/$1/; |
305 |
+ |
return $2; |
306 |
+ |
} |
307 |
+ |
|
308 |
+ |
sub _printstream { |
309 |
+ |
|
310 |
+ |
my $self=shift; |
311 |
+ |
|
312 |
+ |
# Stream output functionality |
313 |
+ |
if ( defined $self->{stream} ) { |
314 |
+ |
print {$self->{stream}} "$self->{streamstore}"; |
315 |
+ |
} |
316 |
|
} |
317 |
|
|
318 |
|
sub _removefromstack { |
322 |
|
my $this; |
323 |
|
|
324 |
|
undef @tempstack; |
246 |
– |
#print "In ----".$#{$stack}; |
325 |
|
# Keep popping until we find our string |
326 |
|
while ( ($this=(pop @{$stack})) ne "$name") { |
327 |
|
push @tempstack, $this; |
332 |
|
$this=pop @tempstack; |
333 |
|
push @{$stack}, $this; |
334 |
|
} |
257 |
– |
#print " Out ----".$#{$stack}; |
335 |
|
} |
336 |
|
|
337 |
|
# |
385 |
|
sub _resetlabels { |
386 |
|
my $self=shift; |
387 |
|
undef $self->{tagvar}; |
388 |
+ |
undef $self->{tagname}; |
389 |
|
} |
390 |
|
|
391 |
|
sub _closelabel { |
393 |
|
|
394 |
|
# Do we have a label name? |
395 |
|
if ( $self->{lastlabel} ne "" ) { |
396 |
< |
$self->{tagvar}{$self->{lastlabel}}=$self->_getstore(); |
396 |
> |
(my $label=$self->{lastlabel})=~tr[A-Z][a-z]; |
397 |
> |
$self->{tagvar}{$label}=$self->_getstore(); |
398 |
|
$self->{lastlabel}=""; |
399 |
|
} |
400 |
|
elsif ( $self->_getstore() ne "") { |
401 |
< |
#Then it must be the tag name |
402 |
< |
($self->{tagname}=$self->_getstore())=~tr/A-Z/a-z/; |
401 |
> |
# Then it must be the tag name |
402 |
> |
if ( ! defined $self->{tagname} ) { |
403 |
> |
($self->{tagname}=$self->_getstore())=~tr/A-Z/a-z/; |
404 |
> |
} |
405 |
> |
else { |
406 |
> |
# do not die anymore - breaks non tag documents |
407 |
> |
#die ">Tag syntax error in $self->{tagname} on line ". |
408 |
> |
# $self->line()." of file \n$self->{filename}"; |
409 |
> |
# -- assume that this is plain text |
410 |
> |
$self->{tagcontext}="text"; |
411 |
> |
$self->_resetstore(); |
412 |
> |
$self->_unshiftstore($self->{tagbuff}); |
413 |
> |
$self->{tagbuff}=""; |
414 |
> |
return; |
415 |
> |
} |
416 |
|
} |
417 |
|
$self->_resetstore(); |
418 |
|
} |
427 |
|
$self->{stringbuff}=$self->{stringbuff}.$char; |
428 |
|
} |
429 |
|
|
430 |
+ |
sub _unshiftstore() { |
431 |
+ |
my $self=shift; |
432 |
+ |
my $char=shift; |
433 |
+ |
|
434 |
+ |
$self->{stringbuff}=$char.$self->{stringbuff}; |
435 |
+ |
} |
436 |
+ |
|
437 |
|
sub _getstore() { |
438 |
|
my $self=shift; |
439 |
|
|