ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/XMLReqUtils.pm
Revision: 1.1
Committed: Tue Jul 26 15:14:00 2005 UTC (19 years, 9 months ago) by sashby
Content type: text/plain
Branch: MAIN
CVS Tags: V1_0_3-p4, V1_0_3-p3, V1_0_3-p2, before110xmlBRmerge, V1_0_4p1, V1_0_3-p1, V1_0_3, V1_0_2, V1_0_2_p1
Branch point for: v103_with_xml, v103_branch
Log Message:
Added XML version of ToolParser classes. Started to add support for upgrade mode of project command

File Contents

# User Rev Content
1 sashby 1.1 #____________________________________________________________________
2     # File: XMLReqUtils.pm
3     #____________________________________________________________________
4     #
5     # Author: Shaun ASHBY <Shaun.Ashby@cern.ch>
6     # Update: 2005-07-26 14:58:38+0200
7     # Revision: $Id$
8     #
9     # Copyright: 2005 (C) Shaun ASHBY
10     #
11     #--------------------------------------------------------------------
12     package BuildSystem::XMLReqUtils;
13     require 5.004;
14    
15     use Exporter;
16    
17     @ISA=qw(Exporter);
18     @EXPORT_OK=qw( );
19    
20     # This package provides all subroutines for supported tags found
21     # in requirements docs:
22     sub new
23     {
24     my $proto=shift;
25     my $class=ref($proto) || $proto;
26     my $self={};
27    
28     bless $self,$class;
29     return $self;
30     }
31    
32     #### Core XML Register Functions ####
33     sub OpenTagHandler()
34     {
35     my $xmlparser=shift;
36     my ($element, %attributes)=@_;
37    
38     # Elementary doc checks:
39     if ($element eq 'doc')
40     {
41     if ($attributes{'type'} ne 'Requirements')
42     {
43     die "SCRAM Error: Unable to parse this document! Wrong type!","\n";
44     }
45     return;
46     }
47    
48     # Store the name of the current tag environment:
49     $self->{currentenv} = $element;
50     $self->simplexmldoc()->checkattributes($element, \%attributes);
51     &{$self->simplexmldoc()->gettagfunction($element)}($element, \%attributes);
52     }
53    
54     sub ClosingTagHandler()
55     {
56     my $xmlparser=shift;
57     my ($element)=@_;
58    
59     if ($element eq 'doc')
60     {
61     return;
62     }
63    
64     if (grep($element eq $_, @{$self->simplexmldoc()->nested()}))
65     {
66     &{$self->simplexmldoc()->gettagfunction($element)}($element, {}, 1);
67     }
68    
69     # Reset the current env (i.e. delete entry):
70     delete $self->{currentenv};
71     }
72    
73     sub CharHandler()
74     {
75     my ($xmlparser, @items) = @_;
76     return if ($items[0] =~ /\s*/);
77    
78     # Check to see if there's a content entry in $self
79     # for the current tag. If so, append the line to it:
80     if (grep($self->{currentenv} eq $_, @{$self->simplexmldoc()->nested()}))
81     {
82     &{$self->simplexmldoc()->gettagfunction($self->{currentenv})}($self->{currentenv},
83     {}, 2, [ @items ]);
84     }
85     }
86    
87     ## Tag routines ##
88     sub requirementstaghandler()
89     {
90     my ($name, $hashref, $nesting) = @_;
91     # Do nothing for char handler:
92     return if ($nesting == 2);
93    
94     if ($nesting == 1)
95     {
96     # Cleanup whatever needs to be cleaned up:
97    
98     }
99     else
100     {
101    
102     }
103    
104     # Return here only if the current element is "requirements":
105     return;
106     }
107    
108     sub usetaghandler()
109     {
110     my ($name, $hashref) = @_;
111     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{USE}},$$hashref{'name'});
112     }
113    
114     sub libtaghandler()
115     {
116     my ($name, $hashref) = @_;
117     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{LIB}},$$hashref{'name'});
118     }
119    
120     sub infotaghandler()
121     {
122     my ($name, $hashref) = @_;
123     $self->{"$self->{levels}->[$self->{nested}]".content}->{INFO} = $hashref;
124     }
125    
126     sub flagstaghandler()
127     {
128     my ($name, $hashref, $nesting) = @_;
129     # Do nothing for char handler:
130     return if ($nesting == 2);
131     # Do nothing for closing tag handler:
132     return if ($nesting == 1);
133    
134     # Extract the flag name and its value:
135     my ($flagname,$flagvaluestring) = each %{$hashref};
136     $flagname =~ tr/[a-z]/[A-Z]/; # Keep flag name uppercase
137     chomp($flagvaluestring);
138     # Split the value on whitespace so we can push all
139     # individual flags into an array:
140     my @flagvalues = split(' ',$flagvaluestring);
141    
142     # Is current tag within another tag block?
143     if ($self->{nested} > 0)
144     {
145     # Check to see if the current flag name is already stored in the hash. If so,
146     # just add the new values to the array of flag values:
147     if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname}))
148     {
149     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname}},@flagvalues);
150     }
151     else
152     {
153     $self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname} = [ @flagvalues ];
154     }
155     }
156     else
157     {
158     if (exists ($self->{content}->{FLAGS}->{$flagname}))
159     {
160     push(@{$self->{content}->{FLAGS}->{$flagname}},@flagvalues);
161     }
162     else
163     {
164     $self->{content}->{FLAGS}->{$flagname} = [ @flagvalues ];
165     }
166     }
167     }
168    
169     sub environmenttaghandler()
170     {
171     my ($name, $hashref, $nesting) = @_;
172     # Do nothing for char handler:
173     return if ($nesting == 2);
174     # Do nothing for closing tag handler:
175     return if ($nesting == 1);
176    
177     # Save a copy of the name of this environment:
178     my $envname=$$hashref{'name'};
179     delete $$hashref{'name'}; # Delete name entry so hash is more tidy
180     # Break the value/default value into its constituent parts:
181     foreach my $t (qw(value default))
182     {
183     if (exists ($$hashref{$t}))
184     {
185     $hashref->{ELEMENTS} = [];
186     map
187     {
188     if ($_ =~ m|\$(.*)?|)
189     {
190     push(@{$hashref->{ELEMENTS}},$1);
191     }
192     } split("/",$hashref->{$t});
193     }
194     }
195    
196     # Before we save $hashref we need to know if there are already
197     # any env tags with the same name. If there are, we must save all
198     # data to an aray of hashes:
199     if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname}))
200     {
201     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname}},$hashref);
202     }
203     else
204     {
205     # No entry yet so just store the hashref:
206     $self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname} = [ $hashref ];
207     }
208     }
209    
210     sub runtimetaghandler()
211     {
212     my ($name, $hashref, $nesting) = @_;
213     # Do nothing for char handler:
214     return if ($nesting == 2);
215     # Do nothing for closing tag handler:
216     return if ($nesting == 1);
217    
218     my $envname;
219    
220     # Break the value/default value into its constituent parts:
221     foreach my $t (qw(value default))
222     {
223     if (exists ($$hashref{$t}))
224     {
225     $hashref->{ELEMENTS} = [];
226     map
227     {
228     # In some cases, we might set a runtime path (e.g. LD_LIBRARY_PATH) to
229     # a proper path value i.e. X:Y. In this case, don't bother adding the string
230     # as a "variable" to ELEMENTS:
231     if ($_ =~ m|\$(.*)?| && $_ !~ /:/)
232     {
233     push(@{$hashref->{ELEMENTS}},$1);
234     }
235     } split("/",$hashref->{$t});
236     }
237     }
238    
239     # Check to see if we have a "type" arg. If so, we use this to create the key:
240     if (exists ($hashref->{'type'}))
241     {
242     my $type=$hashref->{'type'};
243     # Make the type uppercase:
244     $type =~ tr/[a-z]/[A-Z]/;
245     # Rename the environment as "<type>:<env name>":
246     $envname = $type.":".$$hashref{'name'};
247     }
248     else
249     {
250     $envname = $$hashref{'name'};
251     }
252    
253     # Delete name entry so hash is more tidy
254     delete $$hashref{'name'};
255    
256     # Before we save $hashref we need to know if there are already
257     # any runtime tags with the same name. If there are, we must save all
258     # data to an aray of hashes:
259     if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname}))
260     {
261     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname}},$hashref);
262     }
263     else
264     {
265     # No entry yet so just store the hashref:
266     $self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname} = [ $hashref ];
267     }
268     }
269    
270     sub makefiletaghandler()
271     {
272     my ($name, $hashref, $nesting, $string)=@_;
273    
274     if ($nesting == 1)
275     {
276     push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{MAKEFILE}},
277     join('',@{$self->{makefilecontent}}));
278     delete $self->{makefilecontent};
279     }
280     elsif ($nesting == 2)
281     {
282     # Store the text content:
283     push(@{$self->{makefilecontent}}, @$string);
284     }
285     else
286     {
287     # Start the tag:
288     $self->{makefilecontent} = [];
289     }
290     }
291    
292     sub clienttaghandler()
293     {
294     my ($name, $hashref, $nesting) = @_;
295     # Do nothing for char handler:
296     return if ($nesting == 2);
297    
298     if ($nesting == 1)
299     {
300     if ($self->{isarch} == 1)
301     {
302     # If we already have an architecture tag, we must write to tagcontent hash:
303     $self->{tagcontent}->{CLIENT}=$self->{nexttagcontent};
304     delete $self->{nexttagcontent};
305     }
306     else
307     {
308     $self->{content}->{CLIENT}=$self->{tagcontent};
309     }
310    
311     $self->poplevel();
312     }
313     else
314     {
315     $self->pushlevel();
316     }
317     }
318    
319     sub archtaghandler()
320     {
321     my ($name, $hashref, $nesting) = @_;
322     # Do nothing for char handler:
323     return if ($nesting == 2);
324    
325     if ($nesting == 1)
326     {
327     # Need to be able to cope with multiple arch blocks with same arch string:
328     if (exists ($self->{content}->{ARCH}->{$self->{id}->{'name'}}))
329     {
330     # Already have an architecture tag for this arch:
331     while (my ($k,$v) = each %{$self->{tagcontent}})
332     {
333     # If this tag (e.g. LIB, USE, MAKEFILE) already exists and (as we know
334     # it should be) its data is an ARRAY, push it to the store:
335     if (exists ($self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k}) &&
336     ref($v) eq 'ARRAY')
337     {
338     push(@{$self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k}},@$v);
339     }
340     else
341     {
342     # Otherwise (for HASH data) we just store it. Note that, because we do
343     # not loop over the HASH content and check for already existsing keys,
344     # if two arch blocks with same arch name define the same tag (e.g, ENV),
345     # the last occurrence will be kept (i.e. the two values won't be added
346     # to one ENV hash): //FIXME for later....
347     $self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k} = $v;
348     }
349     }
350     }
351     else
352     {
353     $self->{content}->{ARCH}->{$self->{id}->{'name'}}=$self->{tagcontent};
354     }
355    
356     delete $self->{isarch};
357     $self->poplevel();
358     }
359     else
360     {
361     $self->pushlevel($hashref, 1); # Set nested to 1;
362     }
363     }
364    
365     # Data-handling utility functions:
366     sub datastore()
367     {
368     my $obj=shift;
369     $self = $obj;
370     }
371    
372     1;