ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/ActiveDoc/Switcher.pm
Revision: 1.17
Committed: Wed Mar 27 17:35:48 2002 UTC (23 years, 1 month ago) by sashby
Content type: text/plain
Branch: MAIN
CVS Tags: V0_19_6, V0_19_6p1, V0_19_5, SFATEST, V0_19_4, V0_19_4_pre3, V0_19_4_pre2, V0_19_4_pre1
Branch point for: V0_19_4_B
Changes since 1.16: +29 -22 lines
Log Message:
adding some changes. Fixed basics.mk and SCRAM variable.

File Contents

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