ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/ActiveDoc/Switcher.pm
Revision: 1.13.2.5
Committed: Fri May 12 15:00:54 2000 UTC (25 years ago) by williamc
Content type: text/plain
Branch: V0_9branch
CVS Tags: BuildSystemProto1, V0_18_0model, V0_17_1, V0_18_0alpha, V0_17_0, V0_16_4, V0_16_3, V0_16_2, V0_16_1, V0_16_0, V0_15_1, V0_15_0, V0_15_0beta, V0_14_0, V0_12_12_4, V0_12_12_3, V0_13_3, V0_13_2, V0_12_12_2, V0_12_12_1, V0_12_12_0, PlayGround_0, V0_13_1, V0_13_0, V0_12_12, V0_12_11, V0_12_9b, V0_12_10, V0_12_9, V0_12_8, V0_12_7
Branch point for: V0_17branch, V0_16branch, V0_15branch, HPWbranch
Changes since 1.13.2.4: +10 -4 lines
Log Message:
semi-support for non parsed tags + lowercase for label names

File Contents

# Content
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 # Interface
8 # ---------
9 # new(file,objectref) : A new object - filename of file to parse
10 # objectref->of the methods
11 # usetags(tagobjref) : Specify a tagcontainer set to direct to
12 # to the desired routines
13 # usegroupchecker(groupchecker) : Set a groupchecker
14 # parse() : Parse the file
15 # line() : return the current line number of the parse
16 # tagstartline() : return the line number on which the current
17 # tag was opened
18 # stream(filehandle) : stream output to the filehandle if not handled
19 # in any other way
20 package ActiveDoc::Switcher;
21 require 5.001;
22 use Carp;
23
24 sub new {
25 my $class=shift;
26 my $file=shift;
27 my $objectname=shift;
28 my $groupchecker=shift;
29
30 $self = {};
31 $self->{allw}=$objectname;
32 bless $self, $class;
33 $self->_initialise($file);
34 return $self;
35 }
36
37 sub stream {
38 my $self=shift;
39
40 $self->{stream}=shift;
41 }
42
43 sub streamexclude {
44 my $self=shift;
45 my $tag=shift;
46
47 $tag=~tr/A-Z/a-z/;
48 $self->{streamexclude}{$tag}=1;
49 }
50
51 sub _initialise (hash1) {
52 my $self=shift;
53 $self->{filename}=shift;
54
55 # add a default groupchecker
56 use ActiveDoc::GroupChecker;
57 $self->{groupchecker}=GroupChecker->new();
58 $self->{groupchecker}->include("all");
59
60 # Add a default TagContainer
61 use ActiveDoc::TagContainer;
62 $self->{tagcontainer}=ActiveDoc::TagContainer->new();
63
64 }
65
66 sub usetags {
67 my $self=shift;
68 my $tagcontainer=shift;
69
70 $self->{tagcontainer}=$tagcontainer;
71 }
72
73 sub usegroupchecker {
74 my $self=shift;
75 my $ref=shift;
76
77 $self->{groupchecker}=$ref;
78 }
79
80 sub parse {
81 my $self=shift;
82 my $char;
83 my $buf;
84 $self->{linecount}=0;
85 $self->_resetvars();
86 $self->{streamstore}="";
87 $self->{streamtmp}="";
88
89 # Open the file
90 use FileHandle;
91 local $filehandle;
92 $filehandle=FileHandle->new();
93 $filehandle->open("<".$self->{filename})
94 or return 1;
95 # The buffering seems all messed up - best not to use it
96 $filehandle->setvbuf($buf, _IONBF, 3000);
97
98 # Start file processing
99 while ( ($_=<$filehandle>) ) {
100 $self->{linecount}++;
101 $self->{currentline}=$_;
102 $self->{stringpos}=0;
103 while ( ($char=$self->_nextchar()) ne "" ) {
104 $self->_checkchar($char);
105 } # end char while
106 } # End String while loop
107 undef $filehandle;
108 # make sure we close the last buffer
109 $self->_calltag($self->{textcontext}, $self->{textcontext},
110 $self->_getstore());
111 #$self->_printstream();
112 }
113
114 #
115 # return the current line number
116 #
117 sub line {
118 my $self=shift;
119 return $self->{linecount};
120 }
121
122 # return the line the current tag was opened
123 sub tagstartline {
124 my $self=shift;
125 $self->{tagstart};
126 }
127 # --------------- Utility routines ----------------------------
128
129 #
130 # Some initialisation of test suites
131 #
132 sub _resetvars {
133 my $self=shift;
134 $self->{quotes}=0;
135 $self->{lastlabel}="";
136 $self->{textcontext}='none';
137 $self->{tagcontext}="text";
138 $self->_resetstore();
139 }
140
141 #
142 # Check for control characters
143 #
144 sub _checkchar {
145 my $self=shift;
146 my $char=shift;
147 my $string;
148
149
150 # ---- In a tag
151 if ( $self->{tagcontext}=~/tag/ ) {
152 if ( ! $self->_quotetest($char) ) {
153 if ( ! $self->_labeltest($char) ) {
154 if ( $char eq ">") { $self->_closetag(); }
155 else { $self->_putstore($char); }
156 }
157 }
158 }
159 # ------ Outside a tag
160 else {
161 if ( $char eq "<") { $self->_opentag() }
162 else { $self->_putstore($char) }
163 }
164 }
165
166
167 #
168 # Return the next character from the current string buffer
169 #
170 sub _nextchar() {
171 my $self=shift;
172 my $char;
173 $char=substr($self->{currentline},$self->{stringpos}++,1);
174 #print "Debug : Fetching character $char\n";
175
176 # Keep a record for any stream processes
177 $self->{streamstore}=$self->{streamstore}.$char;
178
179 return $char;
180 }
181
182 sub _opentag {
183 my $self=shift;
184 my $char;
185
186 # Keep a record of where the tag started
187 $self->{tagstart}=$self->line();
188
189 # Close the last text segment
190 $self->{streamtmp}=$self->_popstream();
191 $self->_calltag($self->{textcontext}, $self->{textcontext},
192 $self->_getstore());
193 $self->_resetstore();
194 $self->_resetlabels();
195
196 # Do we have an opening or closing tag?
197 if ( ($char=$self->_nextchar()) eq "/" ) { #we have a closing tag
198 $self->{tagcontext}="endtag";
199 }
200 else { # an opening tag
201 $self->{tagcontext}="starttag";
202 $self->_checkchar($char);
203 }
204 #print "\nDebug : Opening $self->{tagcontext}\n";
205 }
206
207 #
208 # Close a tag
209 #
210 sub _closetag {
211 my $self=shift;
212 my $tagroutine;
213
214 # -- Finish off any labels/get tagname
215 $self->_closelabel();
216
217 # -- Call the associated tag function if appropriate
218 if ( defined $self->{tagname} ) {
219 $tagroutine=$self->{tagname}."_".$self->{tagcontext};
220 $self->_calltag($tagroutine, $self->{tagname},
221 $self->{tagvar});
222 #print "\nDebug : Closing Tag $tagroutine\n";
223
224 # -- Now make sure the text context is set for calling routines to
225 # -- deal with text portions outside of tags
226 if ( ($self->{tagcontext} eq "starttag") ) {
227 if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) {
228 push @{$self->{textstack}} , $self->{textcontext};
229 $self->{textcontext}=$self->{tagname};
230 }
231 }
232 else {
233 if ( $#{$self->{textstack}} > -1 ) {
234 if ( $self->{textcontext} eq $self->{tagname} ) {
235 if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) {
236 # -- watch out for valid tags we ignore in this parse
237 $self->{textcontext}=pop @{$self->{textstack}};
238 }
239 }
240 else { #The tag we are closing is not the last one so
241 # we keep our current context.
242 $self->_removefromstack($self->{tagname},$self->{textstack});
243 }
244
245 }
246 else { # more close tags than open ones
247 if ( $self->{tagcontainer}->definescontext($self->{tagname}) ) {
248 print "Warning : Unmatched </...> tag on line ".
249 $self->line()."\n";
250 }
251 }
252 }
253 }
254 # Reset context back to text
255 $self->{tagcontext}="text";
256 }
257
258 sub _calltag {
259 my $self=shift;
260 my $tagroutine=shift;
261 my @args=@_;
262 my $rt;
263 my $found=0;
264
265 if ( $self->{groupchecker}->status() ||
266 ( $self->{tagcontainer}->inquiregroup($tagroutine)) ) {
267 ($rt,$obj)=$self->{tagcontainer}->getroutine($tagroutine);
268 if ( $rt ne "" ) {
269 if ( ! defined $obj ) {
270 &{$rt}( $self->{allw},@_);
271 }
272 else {
273 &{$rt}( $obj,@_);
274 }
275 $found=1;
276 }
277 }
278
279 # stream function
280 if ( ! exists $self->{streamexclude}{$tagroutine} ) {
281 $self->_printstream();
282 }
283 $self->_clearstream();
284 }
285
286 sub _clearstream {
287 my $self=shift;
288 $self->{streamstore}=(($self->{streamtmp} ne "")?$self->{streamtmp}:"");
289 $self->{streamtmp}="";
290 }
291
292 sub _popstream {
293 my $self=shift;
294 $self->{streamstore}=~s/(.*)(.)$/$1/;
295 return $2;
296 }
297
298 sub _printstream {
299
300 my $self=shift;
301
302 # Stream output functionality
303 if ( defined $self->{stream} ) {
304 print {$self->{stream}} "$self->{streamstore}";
305 }
306 }
307
308 sub _removefromstack {
309 my $self=shift;
310 my $name=shift;
311 my $stack=shift;
312 my $this;
313
314 undef @tempstack;
315 #print "In ----".$#{$stack};
316 # Keep popping until we find our string
317 while ( ($this=(pop @{$stack})) ne "$name") {
318 push @tempstack, $this;
319 if ( $#{$stack} < 0 ) { last; }
320 }
321 # Now put them back
322 while ( $#tempstack>-1) {
323 $this=pop @tempstack;
324 push @{$stack}, $this;
325 }
326 #print " Out ----".$#{$stack};
327 }
328
329 #
330 # Quote handling
331 #
332
333 sub _quotetest {
334 my $self=shift;
335 my $char=shift;
336
337 # --- Are we already in a quote context?
338 if ( $self->{quotes} ) {
339 if ( $char eq $self->{openquote} ) {
340 $self->{quotes}=0;
341 }
342 else {
343 $self->_putstore($char);
344 }
345 }
346 # --- Unquoted Context
347 elsif ( (($char eq "\"") || ($char eq "\'") || ($char eq "\`")) ) {
348 $self->{quotes}=1;
349 $self->{openquote}=$char;
350 }
351 else { return 0; } # Return zero if not quoted
352 return 1; # 1 otherwise
353 }
354
355 #
356 # Label handling
357 #
358 sub _labeltest {
359 my $self=shift;
360 my $char=shift;
361
362 # Spaces are markers between tags
363 if ( ($char eq " ") || ($char eq "\n") || ($char eq "\t")) {
364 $self->_closelabel();
365 }
366 # Check for a change in label status
367 elsif ( $char eq "=" ) {
368 $self->{lastlabel}=$self->_getstore();
369 $self->_resetstore();
370 }
371 else {
372 return 0;
373 }
374 return 1;
375 }
376
377 sub _resetlabels {
378 my $self=shift;
379 undef $self->{tagvar};
380 undef $self->{tagname};
381 }
382
383 sub _closelabel {
384 my $self=shift;
385
386 # Do we have a label name?
387 if ( $self->{lastlabel} ne "" ) {
388 (my $label=$self->{lastlabel})=~tr[A-Z][a-z];
389 $self->{tagvar}{$label}=$self->_getstore();
390 $self->{lastlabel}="";
391 }
392 elsif ( $self->_getstore() ne "") {
393 # Then it must be the tag name
394 if ( ! defined $self->{tagname} ) {
395 ($self->{tagname}=$self->_getstore())=~tr/A-Z/a-z/;
396 }
397 else {
398 die ">Tag syntax error in $self->{tagname} on line ".
399 $self->line()." of file \n$self->{filename}";
400 }
401 }
402 $self->_resetstore();
403 }
404
405 #
406 # Character Store management interface
407 #
408 sub _putstore() {
409 my $self=shift;
410 my $char=shift;
411
412 $self->{stringbuff}=$self->{stringbuff}.$char;
413 }
414
415 sub _getstore() {
416 my $self=shift;
417
418 return $self->{stringbuff};
419 }
420
421 sub _resetstore {
422 my $self=shift;
423 $self->{stringbuff}="";
424 }