1 |
+ |
#____________________________________________________________________ |
2 |
+ |
# File: ToolParser.pm |
3 |
+ |
#____________________________________________________________________ |
4 |
+ |
# |
5 |
+ |
# Author: Shaun Ashby <Shaun.Ashby@cern.ch> |
6 |
+ |
# Update: 2004-02-09 20:14:55+0100 |
7 |
+ |
# Revision: $Id$ |
8 |
+ |
# |
9 |
+ |
# Copyright: 2004 (C) Shaun Ashby |
10 |
+ |
# |
11 |
+ |
#-------------------------------------------------------------------- |
12 |
+ |
package BuildSystem::ToolParser; |
13 |
+ |
require 5.004; |
14 |
+ |
|
15 |
+ |
use Exporter; |
16 |
+ |
use ActiveDoc::SimpleDoc; |
17 |
+ |
use Utilities::Verbose; |
18 |
+ |
use BuildSystem::ToolTagUtils; |
19 |
+ |
|
20 |
+ |
@ISA=qw(Exporter Utilities::Verbose); |
21 |
+ |
@EXPORT=qw(); |
22 |
+ |
|
23 |
+ |
# |
24 |
+ |
sub new |
25 |
+ |
############################################################### |
26 |
+ |
# new # |
27 |
+ |
############################################################### |
28 |
+ |
# modified : Thu Nov 13 10:42:08 2003 / SFA # |
29 |
+ |
# params : # |
30 |
+ |
# : # |
31 |
+ |
# function : # |
32 |
+ |
# : # |
33 |
+ |
############################################################### |
34 |
+ |
{ |
35 |
+ |
my $proto=shift; |
36 |
+ |
my $class=ref($proto) || $proto; |
37 |
+ |
my $self={}; |
38 |
+ |
|
39 |
+ |
bless $self,$class; |
40 |
+ |
|
41 |
+ |
$self->{cache}=shift; |
42 |
+ |
$self->{mydoctype}="BuildSystem::ToolParser"; |
43 |
+ |
$self->{mydocversion}="1.1"; |
44 |
+ |
$self->{interactive} = 0; |
45 |
+ |
$self->{content} = {}; |
46 |
+ |
$self->{nested} = 0; |
47 |
+ |
|
48 |
+ |
$self->_initparser(); |
49 |
+ |
|
50 |
+ |
return $self; |
51 |
+ |
} |
52 |
+ |
|
53 |
+ |
sub _initparser |
54 |
+ |
{ |
55 |
+ |
my $self=shift; |
56 |
+ |
|
57 |
+ |
$self->{simpledoc}=ActiveDoc::SimpleDoc->new(); |
58 |
+ |
$self->{simpledoc}->newparse("setup"); |
59 |
+ |
$self->{simpledoc}->addtag("setup","Tool", |
60 |
+ |
\&BuildSystem::ToolTagUtils::tooltagOpen, $self, |
61 |
+ |
"", $self, |
62 |
+ |
\&BuildSystem::ToolTagUtils::tooltagClose, $self); |
63 |
+ |
|
64 |
+ |
$self->{simpledoc}->addtag("setup","Lib", |
65 |
+ |
\&BuildSystem::ToolTagUtils::libtagOpen, $self, |
66 |
+ |
"", $self, |
67 |
+ |
"", $self); |
68 |
+ |
|
69 |
+ |
$self->{simpledoc}->addtag("setup","info", |
70 |
+ |
\&BuildSystem::ToolTagUtils::infotagOpen, $self, |
71 |
+ |
"", $self, |
72 |
+ |
"", $self); |
73 |
+ |
|
74 |
+ |
$self->{simpledoc}->addtag("setup","Use", |
75 |
+ |
\&BuildSystem::ToolTagUtils::usetagOpen, $self, |
76 |
+ |
"", $self, |
77 |
+ |
"", $self); |
78 |
+ |
|
79 |
+ |
$self->{simpledoc}->addtag("setup","Runtime", |
80 |
+ |
\&BuildSystem::ToolTagUtils::runtimetagOpen, $self, |
81 |
+ |
"", $self, |
82 |
+ |
"", $self); |
83 |
+ |
|
84 |
+ |
$self->{simpledoc}->addtag("setup","Flags", |
85 |
+ |
\&BuildSystem::ToolTagUtils::flagstagOpen, $self, |
86 |
+ |
"", $self, |
87 |
+ |
"", $self); |
88 |
+ |
|
89 |
+ |
$self->{simpledoc}->addtag("setup","Client", |
90 |
+ |
\&BuildSystem::ToolTagUtils::clienttagOpen, $self, |
91 |
+ |
"", $self, |
92 |
+ |
\&BuildSystem::ToolTagUtils::clienttagClose, $self); |
93 |
+ |
|
94 |
+ |
$self->{simpledoc}->addtag("setup","Environment", |
95 |
+ |
\&BuildSystem::ToolTagUtils::environmenttagOpen, $self, |
96 |
+ |
"", $self, |
97 |
+ |
"", $self); |
98 |
+ |
|
99 |
+ |
$self->{simpledoc}->addtag("setup","Makefile", |
100 |
+ |
\&BuildSystem::ToolTagUtils::makefiletagOpen, $self, |
101 |
+ |
\&BuildSystem::ToolTagUtils::makefiletagContent, $self, |
102 |
+ |
\&BuildSystem::ToolTagUtils::makefiletagClose, $self); |
103 |
+ |
|
104 |
+ |
$self->{simpledoc}->grouptag("Tool","setup"); |
105 |
+ |
$self->{simpledoc}->addtag("setup","Architecture", |
106 |
+ |
\&BuildSystem::ToolTagUtils::archtagOpen,$self, |
107 |
+ |
"", $self, |
108 |
+ |
\&BuildSystem::ToolTagUtils::archtagClose,$self); |
109 |
+ |
|
110 |
+ |
} |
111 |
+ |
|
112 |
+ |
sub parse |
113 |
+ |
{ |
114 |
+ |
my $self=shift; |
115 |
+ |
my ($tool,$toolver,$file)=@_; |
116 |
+ |
|
117 |
+ |
$self->{tool}=$tool; |
118 |
+ |
$self->{version}=$toolver; |
119 |
+ |
$self->{simpledoc}->filetoparse($file); |
120 |
+ |
$self->verbose("Setup Parse"); |
121 |
+ |
$self->{simpledoc}->parse("setup"); |
122 |
+ |
|
123 |
+ |
delete $self->{simpledoc}; |
124 |
+ |
return $self; |
125 |
+ |
} |
126 |
+ |
|
127 |
+ |
sub pushlevel |
128 |
+ |
{ |
129 |
+ |
my $self = shift; |
130 |
+ |
my ($info, $nextlevel)=@_; |
131 |
+ |
|
132 |
+ |
$self->{id} = $info if (defined $info); |
133 |
+ |
|
134 |
+ |
# Check to see if last tag was arch: if so, ceate new level: |
135 |
+ |
if ($self->{isarch} == 1) |
136 |
+ |
{ |
137 |
+ |
$self->{nested} = 2; |
138 |
+ |
$self->{nexttagcontent}={}; |
139 |
+ |
} |
140 |
+ |
else |
141 |
+ |
{ |
142 |
+ |
$self->{nested} = 1; |
143 |
+ |
$self->{tagcontent}={}; |
144 |
+ |
} |
145 |
+ |
|
146 |
+ |
# Set something which says "last starter tag was ARCH": |
147 |
+ |
if ($nextlevel) |
148 |
+ |
{ |
149 |
+ |
$self->{isarch} = 1; |
150 |
+ |
} |
151 |
+ |
} |
152 |
+ |
|
153 |
+ |
sub poplevel |
154 |
+ |
{ |
155 |
+ |
my $self = shift; |
156 |
+ |
|
157 |
+ |
# Drop level of nesting by one: |
158 |
+ |
$self->{nested}--; |
159 |
+ |
|
160 |
+ |
if ($self->{isarch} != 1) |
161 |
+ |
{ |
162 |
+ |
delete $self->{tagcontent}; |
163 |
+ |
} |
164 |
+ |
} |
165 |
+ |
|
166 |
+ |
sub rmenvdata |
167 |
+ |
{ |
168 |
+ |
my $self=shift; |
169 |
+ |
delete $self->{ENVDATA}; |
170 |
+ |
} |
171 |
+ |
|
172 |
+ |
################################### |
173 |
+ |
## Data Access Methods ## |
174 |
+ |
################################### |
175 |
+ |
sub toolname |
176 |
+ |
{ |
177 |
+ |
my $self=shift; |
178 |
+ |
# Return tool name: |
179 |
+ |
return ($self->{content}->{TOOLNAME}); |
180 |
+ |
} |
181 |
+ |
|
182 |
+ |
sub toolversion |
183 |
+ |
{ |
184 |
+ |
my $self=shift; |
185 |
+ |
# Return tool version: |
186 |
+ |
return ($self->{content}->{TOOLVERSION}); |
187 |
+ |
} |
188 |
+ |
|
189 |
+ |
sub toolcontent |
190 |
+ |
{ |
191 |
+ |
my $self=shift; |
192 |
+ |
# Return whole of content hash: |
193 |
+ |
return $self->{content}; |
194 |
+ |
} |
195 |
+ |
|
196 |
+ |
sub getrawdata() |
197 |
+ |
{ |
198 |
+ |
my $self=shift; |
199 |
+ |
my ($tagtype)=@_; |
200 |
+ |
|
201 |
+ |
# Check to see if we have data for this tag: |
202 |
+ |
if (! exists ($self->{content}->{$tagtype})) |
203 |
+ |
{ |
204 |
+ |
# If not, return: |
205 |
+ |
return 0; |
206 |
+ |
} |
207 |
+ |
|
208 |
+ |
# Check the number of keys for hash referred to by this object. |
209 |
+ |
# If 0, return: |
210 |
+ |
if (ref($self->{content}->{$tagtype}) eq 'HASH') # |
211 |
+ |
{ |
212 |
+ |
if ((my $nkeys=keys %{$self->{content}->{$tagtype}}) > 0) |
213 |
+ |
{ |
214 |
+ |
# Return the data for the tag $tagtype. ARCH is a bit special because |
215 |
+ |
# we want the data for the actual arch (thus, data is on a different level): |
216 |
+ |
if ($tagtype eq 'ARCH') |
217 |
+ |
{ |
218 |
+ |
my $archmatch = {}; |
219 |
+ |
# Check for matching arch key and return hash of relevant data. |
220 |
+ |
# Also must take into account the fact that several arch names may match, e.g. Linux, Linux__2 and |
221 |
+ |
# Linux__2.4 all match. If we find more than one match, collect ALL matching data and return it: |
222 |
+ |
while (my ($k,$v) = each %{$self->{content}->{ARCH}}) |
223 |
+ |
{ |
224 |
+ |
# For every matching architecture we snatch the data and squirrel it away: |
225 |
+ |
if ( $ENV{SCRAM_ARCH} =~ /$k.*/ ) |
226 |
+ |
{ |
227 |
+ |
# Now we check the tags inside the arch block. Note that we do not want to descend |
228 |
+ |
# into CLIENT tags, if these exist. We just want to return all data in the ARCH |
229 |
+ |
# block while making sure that multiple matches are handled correctly. We assume that |
230 |
+ |
# you will only find one CLIENT block inside and ARCH: |
231 |
+ |
while (my ($matchtag, $matchval) = each %{$v}) |
232 |
+ |
{ |
233 |
+ |
if ($matchtag =~ /CLIENT|FLAGS|RUNTIME/) |
234 |
+ |
{ |
235 |
+ |
$archmatch->{$matchtag} = $matchval; |
236 |
+ |
} |
237 |
+ |
else |
238 |
+ |
{ |
239 |
+ |
# Treat tags differently according to whether they are HASHes or ARRAYs: |
240 |
+ |
if (ref($matchval) =~ /HASH/) |
241 |
+ |
{ |
242 |
+ |
while (my ($t, $val) = each %{$matchval}) |
243 |
+ |
{ |
244 |
+ |
if (exists ($archmatch->{$matchtag}->{$t})) |
245 |
+ |
{ |
246 |
+ |
push(@{$archmatch->{$matchtag}->{$t}},@$val); |
247 |
+ |
} |
248 |
+ |
else |
249 |
+ |
{ |
250 |
+ |
$archmatch->{$matchtag}->{$t} = $val; |
251 |
+ |
} |
252 |
+ |
} |
253 |
+ |
} |
254 |
+ |
else # Here we deal with arrays: |
255 |
+ |
{ |
256 |
+ |
if (exists ($archmatch->{$matchtag})) |
257 |
+ |
{ |
258 |
+ |
push(@{$archmatch->{$matchtag}},@$matchval); |
259 |
+ |
} |
260 |
+ |
else |
261 |
+ |
{ |
262 |
+ |
$archmatch->{$matchtag} = $matchval; |
263 |
+ |
} |
264 |
+ |
} |
265 |
+ |
} |
266 |
+ |
} |
267 |
+ |
} |
268 |
+ |
} |
269 |
+ |
# Return the squirrel: |
270 |
+ |
return $archmatch; |
271 |
+ |
|
272 |
+ |
} # End of ARCH tag treatment |
273 |
+ |
else |
274 |
+ |
{ |
275 |
+ |
# Return other tag data: |
276 |
+ |
return $self->{content}->{$tagtype}; |
277 |
+ |
} |
278 |
+ |
} |
279 |
+ |
else |
280 |
+ |
{ |
281 |
+ |
print "Warning: $tagtype tags contain no other tag data!","\n"; |
282 |
+ |
return undef; |
283 |
+ |
} |
284 |
+ |
} |
285 |
+ |
else |
286 |
+ |
{ |
287 |
+ |
# We have an array of data or a scalar: |
288 |
+ |
return $self->{content}->{$tagtype}; |
289 |
+ |
} |
290 |
+ |
} |
291 |
+ |
|
292 |
+ |
sub processrawtool() |
293 |
+ |
{ |
294 |
+ |
my $self=shift; |
295 |
+ |
my ($interactive) = @_; |
296 |
+ |
my $data = []; |
297 |
+ |
my $environments = {}; # Somewhere to collect our environments |
298 |
+ |
|
299 |
+ |
# Set interactive mode if required: |
300 |
+ |
$self->{interactive} = $interactive; |
301 |
+ |
|
302 |
+ |
# Somewhere to store the data: |
303 |
+ |
use BuildSystem::ToolData; |
304 |
+ |
my $tooldataobj = BuildSystem::ToolData->new(); |
305 |
+ |
|
306 |
+ |
# Set the name and version: |
307 |
+ |
$tooldataobj->toolname($self->toolname()); |
308 |
+ |
$tooldataobj->toolversion($self->toolversion()); |
309 |
+ |
|
310 |
+ |
# First, collect all tag data so that we only have non-nested tags. |
311 |
+ |
# Check for architecture-dependent data first, followed by client tags: |
312 |
+ |
foreach $nested_tag (qw( ARCH CLIENT )) |
313 |
+ |
{ |
314 |
+ |
if (my $thisdata=$self->getrawdata($nested_tag)) |
315 |
+ |
{ |
316 |
+ |
foreach my $item (keys %{ $thisdata }) |
317 |
+ |
{ |
318 |
+ |
if ($item eq 'CLIENT') |
319 |
+ |
{ |
320 |
+ |
my $clientdata = $thisdata->{$item}; |
321 |
+ |
foreach my $ckey (keys %{$clientdata}) |
322 |
+ |
{ |
323 |
+ |
$environments->{$ckey} = $clientdata->{$ckey}; |
324 |
+ |
} |
325 |
+ |
} |
326 |
+ |
elsif ($item eq 'ENVIRONMENT' || $item eq 'RUNTIME') |
327 |
+ |
{ |
328 |
+ |
# Check to see if tag already exists before saving: |
329 |
+ |
if (exists($environments->{$item})) |
330 |
+ |
{ |
331 |
+ |
foreach my $ek (keys %{$thisdata}) |
332 |
+ |
{ |
333 |
+ |
if (exists($environments->{$item}->{$ek})) |
334 |
+ |
{ |
335 |
+ |
push(@{$environments->{$item}->{$ek}}, @{$thisdata->{$item}->{$ek}}); |
336 |
+ |
} |
337 |
+ |
else |
338 |
+ |
{ |
339 |
+ |
$environments->{$item}->{$ek} = $thisdata->{$item}->{$ek}; |
340 |
+ |
} |
341 |
+ |
} |
342 |
+ |
} |
343 |
+ |
else |
344 |
+ |
{ |
345 |
+ |
# There isn't an entry yet: |
346 |
+ |
$environments->{$item} = $thisdata->{$item}; |
347 |
+ |
} |
348 |
+ |
} |
349 |
+ |
else |
350 |
+ |
{ |
351 |
+ |
my $data = $thisdata->{$item}; |
352 |
+ |
|
353 |
+ |
if (ref($data) eq 'HASH') |
354 |
+ |
{ |
355 |
+ |
while (my ($f,$v) = each %$data) |
356 |
+ |
{ |
357 |
+ |
$tooldataobj->flags($f,$v); |
358 |
+ |
} |
359 |
+ |
} |
360 |
+ |
else |
361 |
+ |
{ |
362 |
+ |
my $subname = lc($item); |
363 |
+ |
$tooldataobj->$subname($data), if ($#$data != -1); |
364 |
+ |
} |
365 |
+ |
} |
366 |
+ |
} |
367 |
+ |
} |
368 |
+ |
else |
369 |
+ |
{ |
370 |
+ |
# No entry for this nested tag. Proceed. |
371 |
+ |
next; |
372 |
+ |
} |
373 |
+ |
} |
374 |
+ |
|
375 |
+ |
# Now handle all other normal tags: |
376 |
+ |
foreach my $normal_tag (qw( ENVIRONMENT RUNTIME )) |
377 |
+ |
{ |
378 |
+ |
# Do we have some data for this tag? |
379 |
+ |
if (my $thisdata=$self->getrawdata($normal_tag)) |
380 |
+ |
{ |
381 |
+ |
# Add the data to our environments hash. We must check to see if |
382 |
+ |
# there is an entry already: |
383 |
+ |
if (exists($environments->{$normal_tag})) |
384 |
+ |
{ |
385 |
+ |
foreach my $ek (keys %{$thisdata}) |
386 |
+ |
{ |
387 |
+ |
if (exists($environments->{$normal_tag}->{$ek})) |
388 |
+ |
{ |
389 |
+ |
push(@{$environments->{$normal_tag}->{$ek}}, @{$thisdata->{$normal_tag}->{$ek}}); |
390 |
+ |
} |
391 |
+ |
else |
392 |
+ |
{ |
393 |
+ |
$environments->{$normal_tag}->{$ek} = $thisdata->{$normal_tag}->{$ek}; |
394 |
+ |
} |
395 |
+ |
} |
396 |
+ |
} |
397 |
+ |
else |
398 |
+ |
{ |
399 |
+ |
# There isn't an entry yet: |
400 |
+ |
$environments->{$normal_tag} = $thisdata; |
401 |
+ |
} |
402 |
+ |
} |
403 |
+ |
else |
404 |
+ |
{ |
405 |
+ |
# No data so proceed: |
406 |
+ |
next; |
407 |
+ |
} |
408 |
+ |
} |
409 |
+ |
|
410 |
+ |
# Finally, tags that can be stored straight away: |
411 |
+ |
foreach my $tag (qw( FLAGS MAKEFILE )) |
412 |
+ |
{ |
413 |
+ |
my $bdata = $self->getrawdata($tag); |
414 |
+ |
if (ref($bdata) eq 'HASH') |
415 |
+ |
{ |
416 |
+ |
while (my ($f,$v) = each %$bdata) |
417 |
+ |
{ |
418 |
+ |
$tooldataobj->flags($f,$v); |
419 |
+ |
} |
420 |
+ |
} |
421 |
+ |
else |
422 |
+ |
{ |
423 |
+ |
$tooldataobj->makefile($bdata), if ($#$bdata != -1); |
424 |
+ |
} |
425 |
+ |
} |
426 |
+ |
|
427 |
+ |
# Libs and tool dependencise: |
428 |
+ |
foreach my $tag (qw( LIB USE )) |
429 |
+ |
{ |
430 |
+ |
my $bdata = $self->getrawdata($tag); |
431 |
+ |
my $subname = lc($tag); |
432 |
+ |
$tooldataobj->$subname($bdata), if ($#$bdata != -1); |
433 |
+ |
} |
434 |
+ |
|
435 |
+ |
# Also check to see if this tool is a scram-managed project. If |
436 |
+ |
# so, set the SCRAM_PROJECT variable in the ToolData object: |
437 |
+ |
if (exists ($self->{content}->{SCRAM_PROJECT})) |
438 |
+ |
{ |
439 |
+ |
$tooldataobj->scram_project($self->{content}->{SCRAM_PROJECT}); |
440 |
+ |
} |
441 |
+ |
|
442 |
+ |
# Establish the order of parsing the value strings: |
443 |
+ |
my $order = $self->process_environments($environments); |
444 |
+ |
|
445 |
+ |
if ($self->{interactive}) |
446 |
+ |
{ |
447 |
+ |
# Set the values interactively: |
448 |
+ |
$self->interactively_find_settings($tooldataobj, $environments, $order); |
449 |
+ |
} |
450 |
+ |
else |
451 |
+ |
{ |
452 |
+ |
# Set the values: |
453 |
+ |
$self->find_settings($tooldataobj, $environments, $order); |
454 |
+ |
} |
455 |
+ |
|
456 |
+ |
# Return a ToolData object: |
457 |
+ |
return $tooldataobj; |
458 |
+ |
} |
459 |
+ |
|
460 |
+ |
sub process_environments() |
461 |
+ |
{ |
462 |
+ |
my $self=shift; |
463 |
+ |
my ($environments)=@_; |
464 |
+ |
|
465 |
+ |
use BuildSystem::SCRAMGrapher; |
466 |
+ |
my $G = BuildSystem::SCRAMGrapher->new(); |
467 |
+ |
|
468 |
+ |
foreach $envtype (keys %{$environments}) |
469 |
+ |
{ |
470 |
+ |
while (my ($envcontent,$envdata) = each %{$environments->{$envtype}}) |
471 |
+ |
{ |
472 |
+ |
# Add a vertex for the VARIABLE name: |
473 |
+ |
$G->vertex($envcontent); |
474 |
+ |
|
475 |
+ |
foreach my $element (@$envdata) |
476 |
+ |
{ |
477 |
+ |
if (exists($element->{'ELEMENTS'})) |
478 |
+ |
{ |
479 |
+ |
map |
480 |
+ |
{ |
481 |
+ |
# Add a path for each element in ELEMENTS: |
482 |
+ |
$G->edge($envcontent, $_); |
483 |
+ |
} @{$element->{'ELEMENTS'}}; |
484 |
+ |
} |
485 |
+ |
} |
486 |
+ |
} |
487 |
+ |
} |
488 |
+ |
|
489 |
+ |
my $setup_order = $G->sort(); |
490 |
+ |
return $setup_order; |
491 |
+ |
} |
492 |
+ |
|
493 |
+ |
sub find_settings() |
494 |
+ |
{ |
495 |
+ |
my $self=shift; |
496 |
+ |
my ($tooldataobj, $environments, $ordering)=@_; |
497 |
+ |
my $stringtoeval; |
498 |
+ |
my $runtime=[]; |
499 |
+ |
my $path; |
500 |
+ |
|
501 |
+ |
use BuildSystem::ToolSettingValidator; |
502 |
+ |
|
503 |
+ |
my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname()); |
504 |
+ |
|
505 |
+ |
foreach my $envname (@$ordering) |
506 |
+ |
{ |
507 |
+ |
my $type = 'ENVIRONMENT'; |
508 |
+ |
my $envdata = $tsv->environment($type, $envname); |
509 |
+ |
|
510 |
+ |
# Handle single-occurrence variables first (i.e. VAR appears once |
511 |
+ |
# in array of hashes): |
512 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
513 |
+ |
{ |
514 |
+ |
print "\nFinding a value for $envname:","\n"; |
515 |
+ |
print "\n"; |
516 |
+ |
# We have an environment and only one data element: |
517 |
+ |
# Check the lookup DB: |
518 |
+ |
if ($tsv->checkDB($envname)) |
519 |
+ |
{ |
520 |
+ |
print "\tValidating value for $envname (found in tool DB):","\n"; |
521 |
+ |
if ($tsv->validatepath()) |
522 |
+ |
{ |
523 |
+ |
# Save in TSV and store in ToolData object: |
524 |
+ |
$tsv->savevalue($envname,$tsv->pathfromdb()); |
525 |
+ |
$self->store($tooldataobj, $envname, $tsv->pathfromdb()); |
526 |
+ |
} |
527 |
+ |
else |
528 |
+ |
{ |
529 |
+ |
$path = $tsv->findvalue($envname, $envdata); |
530 |
+ |
# Save the value in ToolData object: |
531 |
+ |
$self->store($tooldataobj, $envname, $path); |
532 |
+ |
} |
533 |
+ |
} |
534 |
+ |
else |
535 |
+ |
{ |
536 |
+ |
$path = $tsv->findvalue($envname, $envdata); |
537 |
+ |
# Save in ToolData object: |
538 |
+ |
$self->store($tooldataobj, $envname, $path); |
539 |
+ |
} |
540 |
+ |
} |
541 |
+ |
elsif ($envdata != 0 && $#$envdata > 0) |
542 |
+ |
{ |
543 |
+ |
print "\nFinding a value for $envname:","\n"; |
544 |
+ |
print "\n"; |
545 |
+ |
foreach my $elementdata (@$envdata) |
546 |
+ |
{ |
547 |
+ |
$path = $tsv->findvalue($envname, $elementdata); |
548 |
+ |
# Save in ToolData object: |
549 |
+ |
$self->store($tooldataobj, $envname, $path); |
550 |
+ |
} |
551 |
+ |
} |
552 |
+ |
elsif (exists($ENV{$envname})) |
553 |
+ |
{ |
554 |
+ |
# Nothing to do here: |
555 |
+ |
next; |
556 |
+ |
} |
557 |
+ |
else |
558 |
+ |
{ |
559 |
+ |
push(@$runtime, $envname); |
560 |
+ |
} |
561 |
+ |
} |
562 |
+ |
|
563 |
+ |
# Check that the required libraries exist: |
564 |
+ |
$self->_lib_validate($tooldataobj); |
565 |
+ |
|
566 |
+ |
# Now process the runtime settings: |
567 |
+ |
print "\n"; |
568 |
+ |
print "-------------------------------\n"; |
569 |
+ |
|
570 |
+ |
foreach my $rtname (@$runtime) |
571 |
+ |
{ |
572 |
+ |
my $type = 'RUNTIME'; |
573 |
+ |
my $envdata = $tsv->environment($type, $rtname); |
574 |
+ |
my ($rttype,$realrtname) = split(':',$rtname); |
575 |
+ |
|
576 |
+ |
# Only validate paths: |
577 |
+ |
if ($rtname =~ /:/) |
578 |
+ |
{ |
579 |
+ |
# Handle single-occurrence variables first (i.e. VAR appears once |
580 |
+ |
# in array of hashes): |
581 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
582 |
+ |
{ |
583 |
+ |
print "\nRuntime path settings for $realrtname:","\n"; |
584 |
+ |
print "\n"; |
585 |
+ |
# We have an environment and only one data element: |
586 |
+ |
# Check the lookup DB: |
587 |
+ |
if ($tsv->checkDB($rtname)) |
588 |
+ |
{ |
589 |
+ |
print "\tValidating value for path $realrtname (found in tool DB):","\n"; |
590 |
+ |
if ($tsv->validatepath()) |
591 |
+ |
{ |
592 |
+ |
# Save in TSV and store in ToolData object: |
593 |
+ |
$tsv->savevalue($rtname, $tsv->pathfromdb()); |
594 |
+ |
$tooldataobj->runtime($rtname, [ $tsv->pathfromdb() ]); |
595 |
+ |
} |
596 |
+ |
else |
597 |
+ |
{ |
598 |
+ |
$path = $tsv->findvalue($rtname, $envdata); |
599 |
+ |
# Save the value in ToolData object: |
600 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
601 |
+ |
} |
602 |
+ |
} |
603 |
+ |
else |
604 |
+ |
{ |
605 |
+ |
$path = $tsv->findvalue($rtname, $envdata); |
606 |
+ |
# Save in ToolData object: |
607 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
608 |
+ |
} |
609 |
+ |
} |
610 |
+ |
elsif ($envdata != 0 && $#$envdata > 0) |
611 |
+ |
{ |
612 |
+ |
print "\nRuntime path settings for $realrtname:","\n"; |
613 |
+ |
print "\n"; |
614 |
+ |
foreach my $elementdata (@$envdata) |
615 |
+ |
{ |
616 |
+ |
$path = $tsv->findvalue($rtname, $elementdata); |
617 |
+ |
# Save in ToolData object: |
618 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
619 |
+ |
} |
620 |
+ |
} |
621 |
+ |
else |
622 |
+ |
{ |
623 |
+ |
next; |
624 |
+ |
} |
625 |
+ |
} |
626 |
+ |
else |
627 |
+ |
{ |
628 |
+ |
# Handle runtime variables: |
629 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
630 |
+ |
{ |
631 |
+ |
my $value=''; |
632 |
+ |
$tsv->checkdefaults($envdata, \$value); |
633 |
+ |
print "\n"; |
634 |
+ |
|
635 |
+ |
# Chck to see if the value contains a variable that should be evaluated: |
636 |
+ |
if ($value =~ /$/) |
637 |
+ |
{ |
638 |
+ |
# If so, find the value and substitute. This should work for all |
639 |
+ |
# occurrences of variables because by this point (and because the ordering |
640 |
+ |
# was established at the start) all other variables will have real values: |
641 |
+ |
my $dvalue = $tsv->_expandvars($value); |
642 |
+ |
$value = $dvalue; |
643 |
+ |
} |
644 |
+ |
|
645 |
+ |
print "Runtime variable ",$rtname," set to \"",$value,"\"\n"; |
646 |
+ |
|
647 |
+ |
# Store the variable setting: |
648 |
+ |
$tooldataobj->runtime($rtname, [ $value ]); |
649 |
+ |
} |
650 |
+ |
else |
651 |
+ |
{ |
652 |
+ |
next; |
653 |
+ |
} |
654 |
+ |
} |
655 |
+ |
} |
656 |
+ |
|
657 |
+ |
print "\n"; |
658 |
+ |
} |
659 |
+ |
|
660 |
+ |
sub interactively_find_settings() |
661 |
+ |
{ |
662 |
+ |
my $self=shift; |
663 |
+ |
my ($tooldataobj, $environments, $ordering)=@_; |
664 |
+ |
my $stringtoeval; |
665 |
+ |
my $runtime=[]; |
666 |
+ |
my ($path, $dpath); |
667 |
+ |
|
668 |
+ |
use BuildSystem::ToolSettingValidator; |
669 |
+ |
|
670 |
+ |
my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname(), $self->{interactive}); |
671 |
+ |
|
672 |
+ |
foreach my $envname (@$ordering) |
673 |
+ |
{ |
674 |
+ |
my $type = 'ENVIRONMENT'; |
675 |
+ |
my $envdata = $tsv->environment($type, $envname); |
676 |
+ |
|
677 |
+ |
# Handle single-occurrence variables first (i.e. VAR appears once |
678 |
+ |
# in array of hashes): |
679 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
680 |
+ |
{ |
681 |
+ |
print "\nFinding a value for $envname:","\n"; |
682 |
+ |
print "\n"; |
683 |
+ |
# We have an environment and only one data element: |
684 |
+ |
# Check the lookup DB: |
685 |
+ |
if ($tsv->checkDB($envname)) |
686 |
+ |
{ |
687 |
+ |
print "\tValidating value for $envname (found in tool DB):","\n"; |
688 |
+ |
if ($tsv->validatepath()) |
689 |
+ |
{ |
690 |
+ |
# This is our default: |
691 |
+ |
$dpath = $tsv->pathfromdb(); |
692 |
+ |
# Run promptuser() to see if this value can be kept |
693 |
+ |
# or should be changed: |
694 |
+ |
$path = $tsv->promptuser($envname, $dpath); |
695 |
+ |
# Save in TSV and store in ToolData object: |
696 |
+ |
$tsv->savevalue($envname,$path); |
697 |
+ |
$self->store($tooldataobj, $envname, $path); |
698 |
+ |
} |
699 |
+ |
else |
700 |
+ |
{ |
701 |
+ |
$path = $tsv->ifindvalue($envname, $envdata); |
702 |
+ |
# Save the value in ToolData object: |
703 |
+ |
$self->store($tooldataobj, $envname, $path); |
704 |
+ |
} |
705 |
+ |
} |
706 |
+ |
else |
707 |
+ |
{ |
708 |
+ |
$dpath = $tsv->ifindvalue($envname, $envdata); |
709 |
+ |
# Save in ToolData object: |
710 |
+ |
$self->store($tooldataobj, $envname, $dpath); |
711 |
+ |
} |
712 |
+ |
} |
713 |
+ |
elsif ($envdata != 0 && $#$envdata > 0) |
714 |
+ |
{ |
715 |
+ |
print "\nFinding a value for $envname:","\n"; |
716 |
+ |
print "\n"; |
717 |
+ |
foreach my $elementdata (@$envdata) |
718 |
+ |
{ |
719 |
+ |
$path = $tsv->ifindvalue($envname, $elementdata); |
720 |
+ |
# Save in ToolData object: |
721 |
+ |
$self->store($tooldataobj, $envname, $path); |
722 |
+ |
} |
723 |
+ |
} |
724 |
+ |
elsif (exists($ENV{$envname})) |
725 |
+ |
{ |
726 |
+ |
# Nothing to do here: |
727 |
+ |
next; |
728 |
+ |
} |
729 |
+ |
else |
730 |
+ |
{ |
731 |
+ |
push(@$runtime, $envname); |
732 |
+ |
} |
733 |
+ |
} |
734 |
+ |
|
735 |
+ |
# Check that the required libraries exist: |
736 |
+ |
$self->_lib_validate($tooldataobj); |
737 |
+ |
|
738 |
+ |
# Now process the runtime settings: |
739 |
+ |
print "\n"; |
740 |
+ |
print "-------------------------------\n"; |
741 |
+ |
foreach my $rtname (@$runtime) |
742 |
+ |
{ |
743 |
+ |
my $type = 'RUNTIME'; |
744 |
+ |
my $envdata = $tsv->environment($type, $rtname); |
745 |
+ |
my ($rttype,$realrtname) = split(':',$rtname); |
746 |
+ |
|
747 |
+ |
# Only validate paths: |
748 |
+ |
if ($rtname =~ /:/) |
749 |
+ |
{ |
750 |
+ |
# Handle single-occurrence variables first (i.e. VAR appears once |
751 |
+ |
# in array of hashes): |
752 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
753 |
+ |
{ |
754 |
+ |
print "\nRuntime path settings for $realrtname:","\n"; |
755 |
+ |
print "\n"; |
756 |
+ |
# We have an environment and only one data element: |
757 |
+ |
# Check the lookup DB: |
758 |
+ |
if ($tsv->checkDB($rtname)) |
759 |
+ |
{ |
760 |
+ |
print "\tValidating value for path $realrtname (found in tool DB):","\n"; |
761 |
+ |
if ($tsv->validatepath()) |
762 |
+ |
{ |
763 |
+ |
$dpath = $tsv->pathfromdb(); |
764 |
+ |
# Run promptuser() to see if this value can be kept |
765 |
+ |
# or should be changed: |
766 |
+ |
$path = $tsv->promptuser($rtname, $dpath); |
767 |
+ |
# Save in TSV and store in ToolData object: |
768 |
+ |
$tsv->savevalue($rtname, $path); |
769 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
770 |
+ |
} |
771 |
+ |
else |
772 |
+ |
{ |
773 |
+ |
$dpath = $tsv->ifindvalue($rtname, $envdata); |
774 |
+ |
# Save the value in ToolData object: |
775 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
776 |
+ |
} |
777 |
+ |
} |
778 |
+ |
else |
779 |
+ |
{ |
780 |
+ |
$path = $tsv->ifindvalue($rtname, $envdata); |
781 |
+ |
# Save in ToolData object: |
782 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
783 |
+ |
} |
784 |
+ |
} |
785 |
+ |
elsif ($envdata != 0 && $#$envdata > 0) |
786 |
+ |
{ |
787 |
+ |
print "\nRuntime path settings for $realrtname:","\n"; |
788 |
+ |
print "\n"; |
789 |
+ |
foreach my $elementdata (@$envdata) |
790 |
+ |
{ |
791 |
+ |
$path = $tsv->ifindvalue($rtname, $elementdata); |
792 |
+ |
# Save in ToolData object: |
793 |
+ |
$tooldataobj->runtime($rtname, [ $path ]); |
794 |
+ |
} |
795 |
+ |
} |
796 |
+ |
else |
797 |
+ |
{ |
798 |
+ |
next; |
799 |
+ |
} |
800 |
+ |
} |
801 |
+ |
else |
802 |
+ |
{ |
803 |
+ |
# Handle runtime variables: |
804 |
+ |
if ($envdata != 0 && $#$envdata == 0) # One element only! |
805 |
+ |
{ |
806 |
+ |
my $dvalue=''; |
807 |
+ |
$tsv->checkdefaults($envdata, \$dvalue); |
808 |
+ |
print "\n"; |
809 |
+ |
my $value = $tsv->promptuserforvar($rtname, $dvalue); |
810 |
+ |
# Store the variable setting: |
811 |
+ |
$tooldataobj->runtime($rtname, [ $value ]); |
812 |
+ |
} |
813 |
+ |
else |
814 |
+ |
{ |
815 |
+ |
next; |
816 |
+ |
} |
817 |
+ |
} |
818 |
+ |
} |
819 |
+ |
|
820 |
+ |
print "\n"; |
821 |
+ |
} |
822 |
+ |
|
823 |
+ |
sub store() |
824 |
+ |
{ |
825 |
+ |
my $self=shift; |
826 |
+ |
my ($tooldataobj, $envname, $path) = @_; |
827 |
+ |
my $subrtn = lc($envname); |
828 |
+ |
|
829 |
+ |
if ($tooldataobj->can($subrtn)) |
830 |
+ |
{ |
831 |
+ |
$tooldataobj->$subrtn([ $path ]); |
832 |
+ |
} |
833 |
+ |
else |
834 |
+ |
{ |
835 |
+ |
$tooldataobj->variable_data($envname, $path); |
836 |
+ |
} |
837 |
+ |
} |
838 |
+ |
|
839 |
+ |
sub _lib_validate() |
840 |
+ |
{ |
841 |
+ |
my $self=shift; |
842 |
+ |
my ($toolobj)=@_; |
843 |
+ |
my $errorstatus = { 0 => $main::good."[OK]".$main::normal, 1 => $main::error."[ERROR]".$main::normal }; |
844 |
+ |
my $libsfound={}; |
845 |
+ |
|
846 |
+ |
# Firstly, we check to see if there are libraries provided by this tool: |
847 |
+ |
my @libraries = $toolobj->lib(); |
848 |
+ |
my @libpaths = $toolobj->libdir(); |
849 |
+ |
|
850 |
+ |
foreach my $ldir (@libpaths) |
851 |
+ |
{ |
852 |
+ |
my $full_libname_glob="lib".$lib."*.*"; |
853 |
+ |
# Change to lib dir so we avoid the very long paths in our glob: |
854 |
+ |
chdir($ldir); |
855 |
+ |
# Next we use a glob to get libs matching this string (so we |
856 |
+ |
# can see if there's a shared or archive lib): |
857 |
+ |
my @possible_libs = glob($full_libname_glob); |
858 |
+ |
# |
859 |
+ |
map |
860 |
+ |
{ |
861 |
+ |
$_ =~ s/\.so*|\.a*//g; # Remove all endings |
862 |
+ |
# Store in our hash of found libs: |
863 |
+ |
$libsfound->{$_} = 1; |
864 |
+ |
} @possible_libs; |
865 |
+ |
} |
866 |
+ |
|
867 |
+ |
# Next we iterate over the list of libraries in our tool and |
868 |
+ |
# see if it was found in one of the libdirs: |
869 |
+ |
print "\n\n", if ($#libraries != -1); |
870 |
+ |
foreach my $library (@libraries) |
871 |
+ |
{ |
872 |
+ |
# Good status: |
873 |
+ |
my $errorid = 0; |
874 |
+ |
if (! exists ($libsfound->{'lib'.$library})) |
875 |
+ |
{ |
876 |
+ |
# Check in system library dirs: |
877 |
+ |
if ($self->_check_system_libs($library)) |
878 |
+ |
{ |
879 |
+ |
$errorid = 0; |
880 |
+ |
} |
881 |
+ |
else |
882 |
+ |
{ |
883 |
+ |
$errorid = 1; |
884 |
+ |
} |
885 |
+ |
} |
886 |
+ |
printf("* Library check %-10s for lib%-12s\n",$errorstatus->{$errorid}, $library); |
887 |
+ |
} |
888 |
+ |
|
889 |
+ |
print "\n"; |
890 |
+ |
} |
891 |
+ |
|
892 |
+ |
sub _check_system_libs() |
893 |
+ |
{ |
894 |
+ |
my $self=shift; |
895 |
+ |
my ($lib)=@_; |
896 |
+ |
my $libsfound = {}; |
897 |
+ |
my $systemdirs = [ qw( /lib /usr/lib /usr/local/lib /usr/X11R6/lib ) ]; |
898 |
+ |
my $full_libname_glob="lib".$lib."*.*"; |
899 |
+ |
my $found = 0; |
900 |
+ |
|
901 |
+ |
foreach my $dir (@$systemdirs) |
902 |
+ |
{ |
903 |
+ |
# Change to lib dir so we avoid the very long paths in our glob: |
904 |
+ |
chdir($dir); |
905 |
+ |
# Next we use a glob to get libs matching this string (so we |
906 |
+ |
# can see if there's a shared or archive lib): |
907 |
+ |
my @possible_libs = glob($full_libname_glob); |
908 |
+ |
# |
909 |
+ |
map |
910 |
+ |
{ |
911 |
+ |
$_ =~ s/\.so*|\.a*//g; # Remove all endings |
912 |
+ |
# Store in our hash of found libs: |
913 |
+ |
$libsfound->{$_} = 1; |
914 |
+ |
} @possible_libs; |
915 |
+ |
} |
916 |
+ |
|
917 |
+ |
# See if we find the library in the system lib directories: |
918 |
+ |
if (! exists ($libsfound->{'lib'.$library})) |
919 |
+ |
{ |
920 |
+ |
$found = 1; |
921 |
+ |
} |
922 |
+ |
|
923 |
+ |
return $found; |
924 |
+ |
} |
925 |
+ |
|
926 |
+ |
1; |