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

# 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 # 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 package ActiveDoc::Switcher;
20 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 $self->{tagcontainer}=ActiveDoc::TagContainer->new();
48
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 or return 1;
76 # or carp "Switcher: Cannot open $self->{filename} $! \n";
77
78 print "Starting Parse $self->{filename}\n";
79 # 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 print "Exiting Parse $self->{filename}\n";
90 }
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 }