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

# Content
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;