ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/Utilities/Switcher.pm
(Generate patch)

Comparing COMP/SCRAM/src/Utilities/Switcher.pm (file contents):
Revision 1.2 by williamc, Mon Mar 1 11:01:36 1999 UTC vs.
Revision 1.6 by williamc, Thu Jun 17 14:51:15 1999 UTC

# Line 4 | Line 4
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(hash,file,objectref,[groupchecker]) : A new object requires a hash of
10 + #                                           labels->routine references
11 + #                                           filename of pfile to parse
12 + #                                           objectref->of the methods associated#                                           with the labels
13 + #                                           groupchecker for control of calling
14 + #                                           tag groups (on/off)
15 + # parse()                   : Parse the file                            
16 + # checkparam($name,$par)    : Exit with an error message if parameter
17 + #                             is undefined in tag $name
18 + # line()                    : return the current line number of the parse
19  
20   package Switcher;
21   require 5.001;
10 require Exporter;
22   use Carp;
12 @ISA    = qw(Exporter);
23  
24   sub new {
25          my $class=shift;
26          my $hash=shift;
27          my $file=shift;
28 +        my $objectname=shift;
29 +        my $groupchecker=shift;
30 +
31          my $self = {};
32 +        $self->{allw}=$objectname;
33          bless $self, $class;
34 <        $self->_initialise($hash,$file);
34 >        $self->_initialise($hash,$file,$groupchecker);
35 >        $self->_resetvars();
36          return $self;
37   }
38  
39   sub _initialise (hash1) {
40          my $self=shift;
41          my $inlabelhash=shift;
42 +        $self->{filename}=shift;
43 +        my $groupchecker=shift;
44 +
45          my $newkey;
46          my $key;        
29        $self->{filename}=shift;
47          $self->{labelhash}={};
48          $self->{Strict_no_cr}='yes'; # set to 'no' to retain \n's
49  
33        # setup SGML type tag definitions
34        # Others may be added without problems but ensure to provide
35        # a closure with a hash value of the correct type
36        # No capitals thanks.
37        %{$self->{opencontext}}=(
38                '<' => 'starttag',
39                '</' => 'endtag'
40        );
41        %{$self->{closecontext}}= (
42                ">" => 'tag'
43                        );
44
50          # Fill in the blanks in the user supplied hash
51          if ( ! ( defined $$inlabelhash{'none'} )) { # check for none target
52                  $$inlabelhash{'none'}='none';
# Line 69 | Line 74 | sub _initialise (hash1) {
74          $taglabel="";
75          $self->{tagblock}=[];
76          @{$self->{lastcon}}= qw(none);
77 +
78 +        # Add a groupchecker
79 +        if ( $groupchecker eq "" ) {
80 +          use Utilities::GroupChecker;
81 +          $self->{groupchecker}=GroupChecker->new();
82 +          $self->{groupchecker}->include("all");
83 +        }
84 +        else {
85 +          $self->{groupchecker}=$groupchecker;
86 +        }
87   }
88  
89  
90   sub parse {
91          my $self=shift;
92 <        my $mykey="";
78 <        my $key;
79 <        my $word;
80 <        my $filein="";
92 >        my $char;
93          $self->{linecount}=0;
94 +
95 +        # Open the file
96          use FileHandle;
97          my $filehandle=FileHandle->new();
98          open( $filehandle , "$self->{filename}" )
99                  or carp "Switcher: Cannot open $self->{filename} $! \n";
100 +
101 +        # Start file processing
102          while ( <$filehandle> ) {
87         if ( $self->{Strict_no_cr} eq 'yes' ) {
88          chomp;
89         }
90         @{$self->{words}}=split /\b/;
103           $self->{linecount}++;
104 < WHILELOOP: while ( ($word=shift @{$self->{words}}) ne "" ) {
105 < #       print $word." --- Word\n";
106 <           if  ( $word=~/(>)(<.*)/ ) {
107 <                unshift @{$self->{words}}, $2;
108 <                $word=$1;
109 <           }
98 <           #test against opencontext
99 <           foreach $mykey ( keys  ( %{$self->{opencontext}}) ) {
100 <                if ( $word=~/$mykey/i ) {
101 <                  # Send current tagblock (if its not empty)
102 <                  # to the Lastest Context Routine
103 <                  $self->_closeprevious();
104 <                  # Now carry on the parse
105 <                  $self->{InTag}=${$self->{opencontext}}{$mykey};
106 <                  $#{$self->{tagblock}}=-1;
107 <                  next WHILELOOP;
108 <                }
109 <            }
110 <            #test against closed context
111 <            foreach $key ( keys %{$self->{closecontext}} ) {
112 <                if ( $word=~/$key/i ) {
113 <                   if ( $self->{InTag}=~/${$self->{closecontext}}{$key}/ ) {
114 <                        $temp=(shift @{$self->{tagblock}});
115 <                        $temp=~tr[A-Z][a-z];
116 <                        $rtname=($temp)."_".$self->{InTag};
117 <                        $self->{InTag}="none";
118 <                        # Do we call the tag init routine?
119 <                        if ( ( defined ( ${$self->{labelhash}}{$rtname} )) &&
120 <                          ( ! ( ${$self->{labelhash}}{$rtname}=~/none/i )) ) {
121 <                          &{${$self->{labelhash}}{$rtname}}( $temp,
122 <                                @{$self->{tagblock}});
123 <                        }
124 <                        $self->_flipcontext($temp);    
125 <                        $#{$self->{tagblock}}= -1;
126 <                        next WHILELOOP;
127 <                   }
128 <                   else {
129 <                        die "Unmatched \"$key\" on line $self->{linecount}"    
130 <                                         if $self->{InTag} eq "none";
131 <                        die "Error: Wrong closure \"$key\" on line $self->{linecount}";
132 <                   }
133 <                }
134 <          }
135 <          push @{$self->{tagblock}}, $word;
136 <         } #end word while
137 <        } #end fileglob while
138 <        $self->_closeprevious();
104 >         $self->{currentline}=$_;
105 >         $self->{stringpos}=0;
106 >         while ( ($char=$self->_nextchar()) ne "" ) {
107 >           $self->_checkchar($char);
108 >         } # end char while
109 >        } # End String while loop
110          close $filehandle;
111   }
112  
113 < sub context ($key) {
113 > sub checkparam($name, $key) {
114          my $self=shift;
115 <        my $key=shift;
116 <        $key=~tr[A-Z][a-z];
117 <        return ( ${$self->{ContextHash}}{$key} );
115 >        my $name=shift;
116 >        my $key=shift;
117 >
118 >        if ( ! defined $self->{tagvar}{$key} ) {
119 >           print "Switcher: Badly formed $name tag -".
120 >                        " undefined $key parameter\n";
121 >           exit 1;
122 >        }
123   }
124  
125 + #
126 + # return the current line number
127 + #
128 + sub line {
129 +        my $self=shift;
130 +        return $self->{linecount};
131 + }
132 + # --------------- Utility routines ----------------------------
133 +
134 + #
135 + # Some initialisation of test suites
136 + #
137 + sub _resetvars {
138 +        my $self=shift;
139 +        $self->{quotes}=0;
140 +        $self->{lastlabel}="";
141 +        $self->{textcontext}='none';
142 +        $self->{tagcontext}="text";
143 +        $self->_resetstore();
144 + }
145  
146 < # convert array of value=constants to a hash
147 < # returns reference to the array
148 < sub SetupValueHash(reftoarray) {
149 <        my $self=shift;
150 <        my $arrayref=shift;
151 <        my $side="r";
152 <        my $key='';
153 <        my $thiskey;
154 <        my $wordto="";
155 <        my $word;
156 <        my $quotes=0;
157 <        local $varhash;
158 <
159 <        $varhash = {};
160 <        foreach $word ( @$arrayref ) {
161 <           chomp;
162 <           if ( $word=~/=/) {
163 <                $side="l";
164 <                if ( $word=~s/^=// ) {
165 <                   unshift @$arrayref, $word;
166 <                }
167 <                if ( $word=~s/^.*=// ) {
168 <                  ($thiskey=$word)=~tr[A-Z][a-z]; #keys all lower case
169 <                  $key=$key.$thiskey;
170 <                }
171 <                next;
172 <           }
173 <           if ( $word=~/\"/ ) {
174 <                $quotes=  ( ! $quotes);
175 <                if ( $word=~s/^"// ) {
176 <                   unshift @$arrayref, $word;
177 <                }
178 <                next;
179 <           }
180 <           if ( ( $word=~/\s/ ) && ( ! $quotes) ) {
181 <                $side="r";
182 <                if ( $key=~/./) {
183 <                  $$varhash{$key}=$wordto;
184 <                }
185 <                $key='';
186 <                $wordto="";
187 <                next;
188 <           }
189 <           if ( $side=~/r/) {  
190 <                ($thiskey=$word)=~tr[A-Z][a-z]; #keys all lower case
191 <                $key=$key.$thiskey;
192 <           }
193 <           else {
194 <                $wordto=$wordto.$word;
195 <           }
196 <        }      
197 <        if ( $side=~/l/ ) { $$varhash{$key}=$wordto; }
198 <        return $varhash;
199 < }
200 <
201 < sub _flipcontext(Hashkey) {
202 <        my $self=shift;
203 <        my $key = shift;
204 <        ${$self->{ContextHash}}{$key}=(! ${$self->{ContextHash}}{$key});
205 <        # sort out the context stack
206 <        if ( ! ${$self->{ContextHash}}{$key} ) {
207 <                pop @{$self->{lastcon}};        
208 < #      print "** poping ".$key."\n";
146 > #
147 > # Check for control characters
148 > #
149 > sub _checkchar {
150 >        my $self=shift;
151 >        my $char=shift;
152 >        my $string;
153 >
154 >        # ---- In a tag
155 >        if ( $self->{tagcontext}=~/tag/ ) {
156 >           if ( ! $self->_quotetest($char) ) {
157 >            if ( ! $self->_labeltest($char) ) {
158 >             if ( $char eq ">") { $self->_closetag(); }
159 >             else { $self->_putstore($char); }
160 >            }
161 >           }  
162 >        }
163 >        # ------ Outside a tag
164 >        else {
165 >           if ( $char eq "<") { $self->_opentag() }
166 >           else { $self->_putstore($char) }
167 >        }
168 > }
169 >
170 >
171 > #
172 > # Return the next character from the current string buffer
173 > #
174 > sub _nextchar() {
175 >        my $self=shift;
176 >        my $char;
177 >        $char=substr($self->{currentline},$self->{stringpos}++,1);
178 > #       print "Debug : Fetching character $char\n";
179 >        return $char;
180 > }
181 >
182 > sub _opentag {
183 >        my $self=shift;
184 >        my $char;
185 >
186 >        # Close the last text segment
187 >        $self->_calltag($self->{textcontext}, $self->{textcontext},
188 >                                                        $self->_getstore());
189 >        $self->_resetstore();
190 >        $self->_resetlabels();
191 >
192 >        # Do we have an opening or closing tag?
193 >        if ( ($char=$self->_nextchar()) eq "/" ) { #we have a closing tag
194 >          $self->{tagcontext}="endtag";
195 >        }
196 >        else { # an opening tag
197 >          $self->{tagcontext}="starttag";
198 >          $self->_checkchar($char);
199 >        }
200 >        #print "\nDebug : Opening $self->{tagcontext}\n";
201 > }
202 >
203 > #
204 > # Close a tag
205 > #
206 > sub _closetag {
207 >        my $self=shift;
208 >        my $tagroutine;
209 >
210 >        # -- Finish off any labels/get tagname
211 >        $self->_closelabel();
212 >        
213 >        # -- Call the associated tag function if appropriate
214 >        $tagroutine=$self->{tagname}."_".$self->{tagcontext};
215 >        $self->_calltag($tagroutine, $self->{tagname},
216 >                                                        $self->{tagvar});
217 >        #print "\nDebug : Closing Tag $tagroutine\n";
218 >
219 >        # -- Now make sure the text context is set for calling routines to
220 >        # -- deal with text portions outside of tags
221 >        if ( $self->{tagcontext} eq "starttag" ) {
222 >          push @{$self->{textstack}} , $self->{textcontext};
223 >          $self->{textcontext}=$self->{tagname};
224          }
225          else {
226 < #       print "** pushing ".$key."\n";
227 <                push @{$self->{lastcon}}, $key;
226 >          if ( $#{$self->{textstack}} > -1 ) {
227 >            if ( $self->{textcontext} eq $self->{tagname} ) {  
228 >               $self->{textcontext}=pop @{$self->{textstack}};
229 >            }
230 >            else { #The tag we are closing is not the last one so
231 >                   # we keep our current context.
232 >               $self->_removefromstack($self->{tagname},$self->{textstack});
233 >            }
234 >
235 >          }
236 >          else { # more close tags than open ones
237 >             print "Warning : Unmatched </...> tag on line ".
238 >                                        $self->line()."\n";    
239 >          }
240          }
241 +        # Reset context back to text
242 +        $self->{tagcontext}="text";
243   }
244 < sub _closeprevious {
245 <  my $self=shift;
246 <  if ( $#{$self->{tagblock}} != -1  ) {
247 <   if (( defined
248 <        ${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]} ) &&
249 <        ( ! ( ${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]}
250 <                                        =~/none/i )) ) {
251 <    &{ ${$self->{labelhash}}{${$self->{lastcon}}[$#{$self->{lastcon}}]}}(
252 <         ${$self->{lastcon}}[$#{$self->{lastcon}}], @{$self->{tagblock}});
253 <   }
254 <  }
244 >
245 > sub _calltag {
246 >        my $self=shift;
247 >        my $tagroutine=shift;
248 >        my @args=@_;
249 >
250 >        if ( $self->{groupchecker}->status() ) {
251 >             if ( ( exists $self->{labelhash}{$tagroutine})  &&
252 >                ( $self->{labelhash}{$tagroutine}!~/none/i )
253 >                ) {
254 >                &{ ${$self->{labelhash}}{$tagroutine}} (
255 >                        $self->{allw},@_);
256 >               }
257 >        }
258   }
259  
260 < sub checkparam($hash, $name, $key) {
260 > sub _removefromstack {
261          my $self=shift;
262 <        my $hashref=shift;
263 <        my $name=shift;
264 <        my $key=shift;
262 >        my $name=shift;
263 >        my $stack=shift;
264 >        my $this;
265 >
266 >        undef @tempstack;
267 >        #print "In  ----".$#{$stack};
268 >        # Keep popping until we find our string
269 >        while ( ($this=(pop @{$stack})) ne "$name") {
270 >          push @tempstack, $this;
271 >          if ( $#{$stack} < 0 ) { last; }
272 >        }
273 >        # Now put them back
274 >        while ( $#tempstack>-1) {
275 >          $this=pop @tempstack;
276 >          push @{$stack}, $this;
277 >        }
278 >        #print " Out ----".$#{$stack};
279 > }
280  
281 <        if ( ! defined $$hashref{$key} ) {
282 <           print "BootParser: Badly formed $name tag -".
283 <                        " undefined $key parameter\n";
284 <           exit 1;
281 > #
282 > # Quote handling
283 > #
284 >
285 > sub _quotetest {
286 >        my $self=shift;
287 >        my $char=shift;
288 >
289 >        # --- Are we already in a quote context?
290 >        if ( $self->{quotes} ) {
291 >         if ( $char eq $self->{openquote} ) {
292 >           $self->{quotes}=0;
293 >         }
294 >         else {
295 >           $self->_putstore($char);
296 >         }
297 >        }
298 >        # --- Unquoted Context
299 >        elsif ( (($char eq "\"") || ($char eq "\'") || ($char eq "\`")) ) {
300 >           $self->{quotes}=1;
301 >           $self->{openquote}=$char;
302 >        }
303 >        else { return 0; } # Return zero if not quoted
304 >        return 1;          # 1 otherwise
305 > }
306 >
307 > #
308 > # Label handling
309 > #
310 > sub _labeltest {
311 >        my $self=shift;
312 >        my $char=shift;
313 >
314 >        # Spaces are markers between tags
315 >        if ( ($char eq " ") || ($char eq "\n") || ($char eq "\t")) {
316 >          $self->_closelabel();
317 >        }
318 >        # Check for a change in label status
319 >        elsif ( $char eq "=" ) {
320 >                $self->{lastlabel}=$self->_getstore();
321 >                $self->_resetstore();
322          }
323 <        $$hashref{$key}=~s/["']//;
323 >        else {
324 >             return 0;
325 >        }
326 >        return 1;
327 > }
328 >
329 > sub _resetlabels {
330 >        my $self=shift;
331 >        undef $self->{tagvar};
332 > }
333 >
334 > sub _closelabel {
335 >        my $self=shift;
336 >
337 >        # Do we have a label name?
338 >        if ( $self->{lastlabel} ne "" ) {
339 >         $self->{tagvar}{$self->{lastlabel}}=$self->_getstore();
340 >         $self->{lastlabel}="";
341 >        }
342 >        elsif ( $self->_getstore() ne "") {
343 >         #Then it must be the tag name
344 >         $self->{tagname}=$self->_getstore();
345 >        }
346 >        $self->_resetstore();
347 > }
348 >
349 > #
350 > # Character Store management interface
351 > #
352 > sub _putstore() {
353 >        my $self=shift;
354 >        my $char=shift;
355 >
356 >        $self->{stringbuff}=$self->{stringbuff}.$char;
357 > }
358 >
359 > sub _getstore() {
360 >        my $self=shift;
361 >
362 >        return $self->{stringbuff};
363 > }
364 >
365 > sub _resetstore {
366 >        my $self=shift;
367 >        $self->{stringbuff}="";
368 > }
369 >
370 >
371 > # ----------------------------------------------------------
372 > sub context ($key) {
373 >        my $self=shift;
374 >        my $key=shift;
375 >        $key=~tr[A-Z][a-z];
376 >        return ( ${$self->{ContextHash}}{$key} );
377   }
378  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines