ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/ActiveDoc/Switcher.pm
Revision: 1.5
Committed: Wed Sep 29 15:25:32 1999 UTC (25 years, 7 months ago) by williamc
Content type: text/plain
Branch: MAIN
Changes since 1.4: +2 -6 lines
Log Message:
No buffering - use filehandle operators rather than open close etc

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