ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/ActiveDoc/Switcher.pm
Revision: 1.4
Committed: Wed Sep 29 15:17:04 1999 UTC (25 years, 7 months ago) by williamc
Content type: text/plain
Branch: MAIN
Changes since 1.3: +12 -7 lines
Log Message:
Turn off buffering on input

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