ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/ActiveDoc/Switcher.pm
Revision: 1.3
Committed: Wed Sep 29 11:52:28 1999 UTC (25 years, 7 months ago) by williamc
Content type: text/plain
Branch: MAIN
Changes since 1.2: +4 -2 lines
Log Message:
Update for namespaces

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     # 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     # checkparam($name,$par) : Exit with an error message if parameter
16     # is undefined in tag $name
17     # line() : return the current line number of the parse
18    
19 williamc 1.3 package ActiveDoc::Switcher;
20 williamc 1.1 require 5.001;
21     use Carp;
22    
23     sub new {
24     my $class=shift;
25     my $file=shift;
26     my $objectname=shift;
27     my $groupchecker=shift;
28    
29     my $self = {};
30     $self->{allw}=$objectname;
31     bless $self, $class;
32     $self->_initialise($file);
33     return $self;
34     }
35    
36     sub _initialise (hash1) {
37     my $self=shift;
38     $self->{filename}=shift;
39    
40     # add a default groupchecker
41     use ActiveDoc::GroupChecker;
42     $self->{groupchecker}=GroupChecker->new();
43     $self->{groupchecker}->include("all");
44    
45     # Add a default TagContainer
46     use ActiveDoc::TagContainer;
47 williamc 1.3 $self->{tagcontainer}=ActiveDoc::TagContainer->new();
48 williamc 1.1
49     }
50    
51     sub usetags {
52     my $self=shift;
53     my $tagcontainer=shift;
54    
55     $self->{tagcontainer}=$tagcontainer;
56     }
57    
58     sub usegroupchecker {
59     my $self=shift;
60     my $ref=shift;
61    
62     $self->{groupchecker}=$ref;
63     }
64    
65     sub parse {
66     my $self=shift;
67     my $char;
68     $self->{linecount}=0;
69     $self->_resetvars();
70    
71     # Open the file
72     use FileHandle;
73     my $filehandle=FileHandle->new();
74     open( $filehandle , "$self->{filename}" )
75 williamc 1.2 or return 1;
76     # or carp "Switcher: Cannot open $self->{filename} $! \n";
77 williamc 1.1
78 williamc 1.3 print "Starting Parse $self->{filename}\n";
79 williamc 1.1 # Start file processing
80     while ( <$filehandle> ) {
81     $self->{linecount}++;
82     $self->{currentline}=$_;
83     $self->{stringpos}=0;
84     while ( ($char=$self->_nextchar()) ne "" ) {
85     $self->_checkchar($char);
86     } # end char while
87     } # End String while loop
88     close $filehandle;
89 williamc 1.3 print "Exiting Parse $self->{filename}\n";
90 williamc 1.1 }
91    
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     }
102     }
103    
104     #
105     # return the current line number
106     #
107     sub line {
108     my $self=shift;
109     return $self->{linecount};
110     }
111     # --------------- Utility routines ----------------------------
112    
113     #
114     # Some initialisation of test suites
115     #
116     sub _resetvars {
117     my $self=shift;
118     $self->{quotes}=0;
119     $self->{lastlabel}="";
120     $self->{textcontext}='none';
121     $self->{tagcontext}="text";
122     $self->_resetstore();
123     }
124    
125     #
126     # Check for control characters
127     #
128     sub _checkchar {
129     my $self=shift;
130     my $char=shift;
131     my $string;
132    
133     # ---- In a tag
134     if ( $self->{tagcontext}=~/tag/ ) {
135     if ( ! $self->_quotetest($char) ) {
136     if ( ! $self->_labeltest($char) ) {
137     if ( $char eq ">") { $self->_closetag(); }
138     else { $self->_putstore($char); }
139     }
140     }
141     }
142     # ------ Outside a tag
143     else {
144     if ( $char eq "<") { $self->_opentag() }
145     else { $self->_putstore($char) }
146     }
147     }
148    
149    
150     #
151     # Return the next character from the current string buffer
152     #
153     sub _nextchar() {
154     my $self=shift;
155     my $char;
156     $char=substr($self->{currentline},$self->{stringpos}++,1);
157     # print "Debug : Fetching character $char\n";
158     return $char;
159     }
160    
161     sub _opentag {
162     my $self=shift;
163     my $char;
164    
165     # Close the last text segment
166     $self->_calltag($self->{textcontext}, $self->{textcontext},
167     $self->_getstore());
168     $self->_resetstore();
169     $self->_resetlabels();
170    
171     # Do we have an opening or closing tag?
172     if ( ($char=$self->_nextchar()) eq "/" ) { #we have a closing tag
173     $self->{tagcontext}="endtag";
174     }
175     else { # an opening tag
176     $self->{tagcontext}="starttag";
177     $self->_checkchar($char);
178     }
179     #print "\nDebug : Opening $self->{tagcontext}\n";
180     }
181    
182     #
183     # Close a tag
184     #
185     sub _closetag {
186     my $self=shift;
187     my $tagroutine;
188    
189     # -- Finish off any labels/get tagname
190     $self->_closelabel();
191    
192     # -- Call the associated tag function if appropriate
193     $tagroutine=$self->{tagname}."_".$self->{tagcontext};
194     $self->_calltag($tagroutine, $self->{tagname},
195     $self->{tagvar});
196     #print "\nDebug : Closing Tag $tagroutine\n";
197    
198     # -- Now make sure the text context is set for calling routines to
199     # -- deal with text portions outside of tags
200     if ( $self->{tagcontext} eq "starttag" ) {
201     push @{$self->{textstack}} , $self->{textcontext};
202     $self->{textcontext}=$self->{tagname};
203     }
204     else {
205     if ( $#{$self->{textstack}} > -1 ) {
206     if ( $self->{textcontext} eq $self->{tagname} ) {
207     $self->{textcontext}=pop @{$self->{textstack}};
208     }
209     else { #The tag we are closing is not the last one so
210     # we keep our current context.
211     $self->_removefromstack($self->{tagname},$self->{textstack});
212     }
213    
214     }
215     else { # more close tags than open ones
216     print "Warning : Unmatched </...> tag on line ".
217     $self->line()."\n";
218     }
219     }
220     # Reset context back to text
221     $self->{tagcontext}="text";
222     }
223    
224     sub _calltag {
225     my $self=shift;
226     my $tagroutine=shift;
227     my @args=@_;
228     my $rt;
229    
230     if ( $self->{groupchecker}->status() ||
231     ( $self->{tagcontainer}->inquiregroup($tagroutine)) ) {
232     $rt=$self->{tagcontainer}->getroutine($tagroutine);
233     if ( $rt ne "" ) {
234     &{$rt}( $self->{allw},@_);
235     }
236     }
237     }
238    
239     sub _removefromstack {
240     my $self=shift;
241     my $name=shift;
242     my $stack=shift;
243     my $this;
244    
245     undef @tempstack;
246     #print "In ----".$#{$stack};
247     # Keep popping until we find our string
248     while ( ($this=(pop @{$stack})) ne "$name") {
249     push @tempstack, $this;
250     if ( $#{$stack} < 0 ) { last; }
251     }
252     # Now put them back
253     while ( $#tempstack>-1) {
254     $this=pop @tempstack;
255     push @{$stack}, $this;
256     }
257     #print " Out ----".$#{$stack};
258     }
259    
260     #
261     # Quote handling
262     #
263    
264     sub _quotetest {
265     my $self=shift;
266     my $char=shift;
267    
268     # --- Are we already in a quote context?
269     if ( $self->{quotes} ) {
270     if ( $char eq $self->{openquote} ) {
271     $self->{quotes}=0;
272     }
273     else {
274     $self->_putstore($char);
275     }
276     }
277     # --- Unquoted Context
278     elsif ( (($char eq "\"") || ($char eq "\'") || ($char eq "\`")) ) {
279     $self->{quotes}=1;
280     $self->{openquote}=$char;
281     }
282     else { return 0; } # Return zero if not quoted
283     return 1; # 1 otherwise
284     }
285    
286     #
287     # Label handling
288     #
289     sub _labeltest {
290     my $self=shift;
291     my $char=shift;
292    
293     # Spaces are markers between tags
294     if ( ($char eq " ") || ($char eq "\n") || ($char eq "\t")) {
295     $self->_closelabel();
296     }
297     # Check for a change in label status
298     elsif ( $char eq "=" ) {
299     $self->{lastlabel}=$self->_getstore();
300     $self->_resetstore();
301     }
302     else {
303     return 0;
304     }
305     return 1;
306     }
307    
308     sub _resetlabels {
309     my $self=shift;
310     undef $self->{tagvar};
311     }
312    
313     sub _closelabel {
314     my $self=shift;
315    
316     # Do we have a label name?
317     if ( $self->{lastlabel} ne "" ) {
318     $self->{tagvar}{$self->{lastlabel}}=$self->_getstore();
319     $self->{lastlabel}="";
320     }
321     elsif ( $self->_getstore() ne "") {
322     #Then it must be the tag name
323     ($self->{tagname}=$self->_getstore())=~tr/A-Z/a-z/;
324     }
325     $self->_resetstore();
326     }
327    
328     #
329     # Character Store management interface
330     #
331     sub _putstore() {
332     my $self=shift;
333     my $char=shift;
334    
335     $self->{stringbuff}=$self->{stringbuff}.$char;
336     }
337    
338     sub _getstore() {
339     my $self=shift;
340    
341     return $self->{stringbuff};
342     }
343    
344     sub _resetstore {
345     my $self=shift;
346     $self->{stringbuff}="";
347     }