ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolParser.pm
Revision: 1.8.2.3
Committed: Mon Feb 18 10:36:08 2008 UTC (17 years, 2 months ago) by muzaffar
Content type: text/plain
Branch: forBinLess_SCRAM
CVS Tags: V1_2_1b, V1_2_1a, V1_2_3, V1_2_2, V1_2_2_relcand2, V1_2_2_relcand1, V1_2_1, V1_2_0, V1_2_0-cand11, V1_2_0-cand10, V1_2_0-cand9, V1_2_0-cand8, V1_2_0-cand7, V1_2_0-cand6, V1_2_0-cand5, V1_2_0-cand4, V1_2_0-cand3
Branch point for: SCRAM_V2_0
Changes since 1.8.2.2: +24 -41 lines
Log Message:
more cleanup. Fixed for asking user a value of a variable durring batch mode

File Contents

# Content
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: ToolParser.pm,v 1.8.2.2 2008/02/15 17:30:59 muzaffar Exp $
8 #
9 # Copyright: 2004 (C) Shaun Ashby
10 #
11 #--------------------------------------------------------------------
12 package BuildSystem::ToolParser;
13 require 5.004;
14
15 use Exporter;
16 use SCRAM::MsgLog;
17 use ActiveDoc::SimpleDoc;
18 use Utilities::Verbose;
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 $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 $self->{scramdoc}=ActiveDoc::SimpleDoc->new();
48 $self->{scramdoc}->newparse("setup", $self->{mydoctype},'Subs');
49 $self->{envorder}=[];
50
51 return $self;
52 }
53
54 ### Tag handler methods ###
55 sub tool()
56 {
57 my ($object,$name,%attributes)=@_;
58 my $hashref = \%attributes;
59 # A way to distinguish the naming of different nested levels:
60 $self->{levels}=['','tag','nexttag'];
61 $$hashref{'name'} =~ tr[A-Z][a-z];
62
63 # Make sure we only pick up the tool requested:
64 if ( ($self->{tool} eq $$hashref{'name'}) &&
65 ($self->{version} eq $$hashref{'version'} ))
66 {
67 # These variables will be used when expanding settings
68 # in tool variable defs:
69 $ENV{SCRAMToolname} = $$hashref{'name'};
70 $ENV{SCRAMToolversion} = $$hashref{'version'};
71 $self->{content}->{TOOLNAME}=$$hashref{'name'};
72 $self->{content}->{TOOLVERSION}=$$hashref{'version'};
73 }
74 else
75 {
76 print "\n";
77 $::scram->scramerror("Configuration problem! Wanted/actual ".$self->{tool}." tool versions differ (wanted = ".$self->{version}.", downloaded = ".$$hashref{'version'}.")\n");
78 }
79 # Test to see if this doc defines a
80 # scram-managed project or a compiler:
81 if (exists ($$hashref{'type'}))
82 {
83 $$hashref{'type'} =~ tr[A-Z][a-z];
84 $self->{content}->{SCRAM_PROJECT} = 0;
85
86 if ($$hashref{'type'} eq 'scram')
87 {
88 $self->{content}->{SCRAM_PROJECT} = 1;
89 }
90 elsif ($$hashref{'type'} eq 'compiler')
91 {
92 # Is tool a compiler? Store this for retrieval from tool manager obj:
93 $self->{content}->{SCRAM_COMPILER} = 1;
94 }
95 else
96 {
97 $::scram->scramwarn("Unknown type \"".$$hashref{'type'}."\" in tool ".$$hashref{'name'}."\n");
98 }
99 }
100 }
101
102 sub tool_()
103 {
104 delete $self->{levels};
105 delete $self->{id};
106 delete $self->{nested};
107 }
108
109 sub lib()
110 {
111 my ($object,$name,%attributes)=@_;
112 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{LIB}},$attributes{'name'});
113 }
114
115 sub info()
116 {
117 my ($object,$name,%attributes)=@_;
118 $self->{"$self->{levels}->[$self->{nested}]".content}->{INFO} = \%attributes;
119 }
120
121 sub use()
122 {
123 my ($object,$name,%attributes)=@_;
124 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{USE}},$attributes{'name'});
125 }
126
127 sub runtime()
128 {
129 my ($object,$name,%attributes)=@_;
130 my $hashref = \%attributes;
131 my $envname;
132 # Check to see if we have a "type" arg. If so, we use this to create the key:
133 if (exists ($hashref->{'type'}))
134 {
135 my $type=$hashref->{'type'};
136 # Make the type uppercase:
137 $type =~ tr/[a-z]/[A-Z]/;
138 # Rename the environment as "<type>:<env name>":
139 $envname = $type.":".$$hashref{'name'};
140 }
141 else
142 {
143 $envname = $$hashref{'name'};
144 }
145
146 # Delete name entry so hash is more tidy
147 delete $$hashref{'name'};
148
149 # Before we save $hashref we need to know if there are already
150 # any runtime tags with the same name. If there are, we must save all
151 # data to an aray of hashes:
152 if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname}))
153 {
154 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname}},$hashref);
155 }
156 else
157 {
158 # No entry yet so just store the hashref:
159 $self->{"$self->{levels}->[$self->{nested}]".content}->{RUNTIME}->{$envname} = [ $hashref ];
160 }
161 }
162
163 sub flags()
164 {
165 my ($object,$name,%attributes)=@_;
166 # Extract the flag name and its value:
167 my ($flagname,$flagvaluestring) = each %attributes;
168 $flagname =~ tr/[a-z]/[A-Z]/; # Keep flag name uppercase
169 chomp($flagvaluestring);
170 # Split the value on whitespace so we can push all
171 # individual flags into an array:
172 my @flagvalues = split(' ',$flagvaluestring);
173
174 # Is current tag within another tag block?
175 if ($self->{nested} > 0)
176 {
177 # Check to see if the current flag name is already stored in the hash. If so,
178 # just add the new values to the array of flag values:
179 if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname}))
180 {
181 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname}},@flagvalues);
182 }
183 else
184 {
185 $self->{"$self->{levels}->[$self->{nested}]".content}->{FLAGS}->{$flagname} = [ @flagvalues ];
186 }
187 }
188 else
189 {
190 if (exists ($self->{content}->{FLAGS}->{$flagname}))
191 {
192 push(@{$self->{content}->{FLAGS}->{$flagname}},@flagvalues);
193 }
194 else
195 {
196 $self->{content}->{FLAGS}->{$flagname} = [ @flagvalues ];
197 }
198 }
199 }
200
201 sub client()
202 {
203 $self->pushlevel();
204 }
205
206 sub client_()
207 {
208 if ($self->{isarch} == 1)
209 {
210 # If we already have an architecture tag, we must write to tagcontent hash:
211 $self->{tagcontent}->{CLIENT}=$self->{nexttagcontent};
212 delete $self->{nexttagcontent};
213 }
214 else
215 {
216 $self->{content}->{CLIENT}=$self->{tagcontent};
217 }
218
219 $self->poplevel();
220 }
221
222 sub environment()
223 {
224 my ($object,$name,%attributes)=@_;
225 my $hashref = \%attributes;
226 # Save a copy of the name of this environment:
227 my $envname=$$hashref{'name'};
228 delete $$hashref{'name'}; # Delete name entry so hash is more tidy
229 # Before we save $hashref we need to know if there are already
230 # any env tags with the same name. If there are, we must save all
231 # data to an aray of hashes:
232 if (exists ($self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname}))
233 {
234 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname}},$hashref);
235 my @norder=();
236 foreach my $env (@{$self->{envorder}})
237 {
238 if($env ne $envname) {push @norder,$env;}
239 }
240 $self->{envorder}=[];
241 push @{$self->{envorder}},@norder;
242 push @{$self->{envorder}},$envname;
243 }
244 else
245 {
246 # No entry yet so just store the hashref:
247 $self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname} = [ $hashref ];
248 push @{$self->{envorder}},$envname;
249 }
250 }
251
252 sub makefile()
253 {
254 my ($object,$name,%attributes)=@_;
255 }
256
257 sub makefile_()
258 {
259 my ($object,$name,$cdata)=@_;
260 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{MAKEFILE}},
261 join("\n",@$cdata));
262 }
263
264 sub architecture()
265 {
266 my ($object,$name,%attributes)=@_;
267 $self->pushlevel(\%attributes,1); # Set nested to 1;
268 }
269
270 sub architecture_()
271 {
272 # Need to be able to cope with multiple arch blocks with same arch string:
273 if (exists ($self->{content}->{ARCH}->{$self->{id}->{'name'}}))
274 {
275 # Already have an architecture tag for this arch:
276 while (my ($k,$v) = each %{$self->{tagcontent}})
277 {
278 # If this tag (e.g. LIB, USE, MAKEFILE) already exists and (as we know
279 # it should be) its data is an ARRAY, push it to the store:
280 if (exists ($self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k}) &&
281 ref($v) eq 'ARRAY')
282 {
283 push(@{$self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k}},@$v);
284 }
285 else
286 {
287 # Otherwise (for HASH data) we just store it. Note that, because we do
288 # not loop over the HASH content and check for already existsing keys,
289 # if two arch blocks with same arch name define the same tag (e.g, ENV),
290 # the last occurrence will be kept (i.e. the two values won't be added
291 # to one ENV hash: //FIXME for later....)
292 $self->{content}->{ARCH}->{$self->{id}->{'name'}}->{$k} = $v;
293 }
294 }
295 }
296 else
297 {
298 $self->{content}->{ARCH}->{$self->{id}->{'name'}}=$self->{tagcontent};
299 }
300
301 delete $self->{isarch};
302 $self->poplevel();
303 }
304
305 sub parse
306 {
307 my $self=shift;
308 my ($tool,$toolver,$file)=@_;
309 $self->{tool}=$tool;
310 $self->{version}=$toolver;
311 $self->{scramdoc}->filetoparse($file);
312 $self->verbose("Setup Parse");
313 my $fhead='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><doc type="BuildSystem/ToolParser" version="1.0">';
314 my $ftail='</doc>';
315 $self->{scramdoc}->parse("setup",$fhead,$ftail);
316 delete $self->{scramdoc};
317 return $self;
318 }
319
320 sub pushlevel
321 {
322 my $self = shift;
323 my ($info, $nextlevel)=@_;
324
325 $self->{id} = $info if (defined $info);
326
327 # Check to see if last tag was arch: if so, ceate new level:
328 if ($self->{isarch} == 1)
329 {
330 $self->{nested} = 2;
331 $self->{nexttagcontent}={};
332 }
333 else
334 {
335 $self->{nested} = 1;
336 $self->{tagcontent}={};
337 }
338
339 # Set something which says "last starter tag was ARCH":
340 if ($nextlevel)
341 {
342 $self->{isarch} = 1;
343 }
344 }
345
346 sub poplevel
347 {
348 my $self = shift;
349
350 # Drop level of nesting by one:
351 $self->{nested}--;
352
353 if ($self->{isarch} != 1)
354 {
355 delete $self->{tagcontent};
356 }
357 }
358
359 sub rmenvdata
360 {
361 my $self=shift;
362 delete $self->{ENVDATA};
363 }
364
365 ###################################
366 ## Data Access Methods ##
367 ###################################
368 sub toolname
369 {
370 my $self=shift;
371 # Return tool name:
372 return ($self->{content}->{TOOLNAME});
373 }
374
375 sub toolversion
376 {
377 my $self=shift;
378 # Return tool version:
379 return ($self->{content}->{TOOLVERSION});
380 }
381
382 sub toolcontent
383 {
384 my $self=shift;
385 # Return whole of content hash:
386 return $self->{content};
387 }
388
389 sub getrawdata()
390 {
391 my $self=shift;
392 my ($tagtype)=@_;
393
394 # Check to see if we have data for this tag:
395 if (! exists ($self->{content}->{$tagtype}))
396 {
397 # If not, return:
398 return 0;
399 }
400
401 # Check the number of keys for hash referred to by this object.
402 # If 0, return:
403 if (ref($self->{content}->{$tagtype}) eq 'HASH') #
404 {
405 if ((my $nkeys=keys %{$self->{content}->{$tagtype}}) > 0)
406 {
407 # Return the data for the tag $tagtype. ARCH is a bit special because
408 # we want the data for the actual arch (thus, data is on a different level):
409 if ($tagtype eq 'ARCH')
410 {
411 my $archmatch = {};
412 # Check for matching arch key and return hash of relevant data.
413 # Also must take into account the fact that several arch names may match, e.g. Linux, Linux__2 and
414 # Linux__2.4 all match. If we find more than one match, collect ALL matching data and return it:
415 while (my ($k,$v) = each %{$self->{content}->{ARCH}})
416 {
417 # For every matching architecture we snatch the data and squirrel it away:
418 if ( $ENV{SCRAM_ARCH} =~ /$k.*/ )
419 {
420 # Now we check the tags inside the arch block. Note that we do not want to descend
421 # into CLIENT tags, if these exist. We just want to return all data in the ARCH
422 # block while making sure that multiple matches are handled correctly. We assume that
423 # you will only find one CLIENT block inside and ARCH:
424 while (my ($matchtag, $matchval) = each %{$v})
425 {
426 if ($matchtag =~ /CLIENT|FLAGS|RUNTIME/)
427 {
428 $archmatch->{$matchtag} = $matchval;
429 }
430 else
431 {
432 # Treat tags differently according to whether they are HASHes or ARRAYs:
433 if (ref($matchval) =~ /HASH/)
434 {
435 while (my ($t, $val) = each %{$matchval})
436 {
437 if (exists ($archmatch->{$matchtag}->{$t}))
438 {
439 push(@{$archmatch->{$matchtag}->{$t}},@$val);
440 }
441 else
442 {
443 $archmatch->{$matchtag}->{$t} = $val;
444 }
445 }
446 }
447 else # Here we deal with arrays:
448 {
449 if (exists ($archmatch->{$matchtag}))
450 {
451 push(@{$archmatch->{$matchtag}},@$matchval);
452 }
453 else
454 {
455 $archmatch->{$matchtag} = $matchval;
456 }
457 }
458 }
459 }
460 }
461 }
462 # Return the squirrel:
463 return $archmatch;
464
465 } # End of ARCH tag treatment
466 else
467 {
468 # Return other tag data:
469 return $self->{content}->{$tagtype};
470 }
471 }
472 else
473 {
474 print "Warning: $tagtype tags contain no other tag data!","\n";
475 return undef;
476 }
477 }
478 else
479 {
480 # We have an array of data or a scalar:
481 return $self->{content}->{$tagtype};
482 }
483 }
484
485 sub processrawtool()
486 {
487 my $self=shift;
488 my ($interactive) = @_;
489 my $data = [];
490 my $environments = {}; # Somewhere to collect our environments
491
492 # Set interactive mode if required:
493 $self->{interactive} = $interactive;
494
495 # Somewhere to store the data:
496 use BuildSystem::ToolData;
497 my $tooldataobj = BuildSystem::ToolData->new();
498
499 # Set the name and version:
500 $tooldataobj->toolname($self->toolname());
501 $tooldataobj->toolversion($self->toolversion());
502
503 # First, collect all tag data so that we only have non-nested tags.
504 # Check for architecture-dependent data first, followed by client tags:
505 foreach $nested_tag (qw( ARCH CLIENT ))
506 {
507 if (my $thisdata=$self->getrawdata($nested_tag))
508 {
509 foreach my $item (keys %{ $thisdata })
510 {
511 if ($item eq 'CLIENT')
512 {
513 my $clientdata = $thisdata->{$item};
514 foreach my $ckey (keys %{$clientdata})
515 {
516 $environments->{$ckey} = $clientdata->{$ckey};
517 }
518 }
519 elsif ($item eq 'ENVIRONMENT' || $item eq 'RUNTIME')
520 {
521 # Check to see if tag already exists before saving:
522 if (exists($environments->{$item}))
523 {
524 foreach my $ek (keys %{$thisdata})
525 {
526 if (exists($environments->{$item}->{$ek}))
527 {
528 push(@{$environments->{$item}->{$ek}}, @{$thisdata->{$item}->{$ek}});
529 }
530 else
531 {
532 $environments->{$item}->{$ek} = $thisdata->{$item}->{$ek};
533 }
534 }
535 }
536 else
537 {
538 # There isn't an entry yet:
539 $environments->{$item} = $thisdata->{$item};
540 }
541 }
542 else
543 {
544 my $data = $thisdata->{$item};
545
546 if (ref($data) eq 'HASH')
547 {
548 while (my ($f,$v) = each %$data)
549 {
550 $tooldataobj->flags($f,$v);
551 }
552 }
553 else
554 {
555 my $subname = lc($item);
556 $tooldataobj->$subname($data), if ($#$data != -1);
557 }
558 }
559 }
560 }
561 else
562 {
563 # No entry for this nested tag. Proceed.
564 next;
565 }
566 }
567 # Now handle all other normal tags:
568 foreach my $normal_tag (qw( ENVIRONMENT RUNTIME ))
569 {
570 # Do we have some data for this tag?
571 if (my $thisdata=$self->getrawdata($normal_tag))
572 {
573 # Add the data to our environments hash. We must check to see if
574 # there is an entry already:
575 if (exists($environments->{$normal_tag}))
576 {
577 foreach my $ek (keys %{$thisdata})
578 {
579 if (exists($environments->{$normal_tag}->{$ek}))
580 {
581 push(@{$environments->{$normal_tag}->{$ek}}, @{$thisdata->{$normal_tag}->{$ek}});
582 }
583 else
584 {
585 $environments->{$normal_tag}->{$ek} = $thisdata->{$normal_tag}->{$ek};
586 }
587 }
588 }
589 else
590 {
591 # There isn't an entry yet:
592 $environments->{$normal_tag} = $thisdata;
593 }
594 }
595 else
596 {
597 # No data so proceed:
598 next;
599 }
600 }
601
602 # Finally, tags that can be stored straight away:
603 foreach my $tag (qw( FLAGS MAKEFILE ))
604 {
605 my $bdata = $self->getrawdata($tag);
606 if (ref($bdata) eq 'HASH')
607 {
608 while (my ($f,$v) = each %$bdata)
609 {
610 $tooldataobj->flags($f,$v);
611 }
612 }
613 else
614 {
615 $tooldataobj->makefile($bdata), if ($#$bdata != -1);
616 }
617 }
618
619 # Libs and tool dependencise:
620 foreach my $tag (qw( LIB USE ))
621 {
622 my $bdata = $self->getrawdata($tag);
623 my $subname = lc($tag);
624 $tooldataobj->$subname($bdata), if ($#$bdata != -1);
625 }
626
627 # Also check to see if this tool is a scram-managed project. If
628 # so, set the SCRAM_PROJECT variable in the ToolData object:
629 if (exists ($self->{content}->{SCRAM_PROJECT}))
630 {
631 $tooldataobj->scram_project($self->{content}->{SCRAM_PROJECT});
632 }
633
634 # And check to see if this tool is a compiler. If so, set
635 # the SCRAM_COMPILER variable in the ToolData object:
636 if (exists ($self->{content}->{SCRAM_COMPILER}))
637 {
638 $tooldataobj->scram_compiler($self->{content}->{SCRAM_COMPILER});
639 }
640
641 my @order=(); push @order,@{$self->{envorder}};
642 my %uorder=(); map {$uorder{$_}=1} @order;
643 foreach my $type (qw (ENVIRONMENT RUNTIME))
644 {
645 if (exists $environments->{$type})
646 {
647 foreach my $env (keys %{$environments->{$type}})
648 {
649 if (!exists $uorder{$env}){$uorder{$env}=1; push @order,$env;}
650 }
651 }
652 }
653 if ($self->{interactive})
654 {
655 # Set the values interactively:
656 $self->interactively_find_settings($tooldataobj, $environments, \@order);
657 }
658 else
659 {
660 # Set the values:
661 $self->find_settings($tooldataobj, $environments, \@order);
662 }
663
664 # Return a ToolData object:
665 return $tooldataobj;
666 }
667
668 sub find_settings()
669 {
670 my $self=shift;
671 my ($tooldataobj, $environments, $ordering)=@_;
672 my $stringtoeval;
673 my $runtime=[];
674 my $path;
675
676 use BuildSystem::ToolSettingValidator;
677
678 my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname());
679
680 foreach my $envname (@$ordering)
681 {
682 my $type = 'ENVIRONMENT';
683 my $envdata = $tsv->environment($type, $envname);
684
685 # Handle single-occurrence variables first (i.e. VAR appears once
686 # in array of hashes):
687 if ($envdata != 0 && $#$envdata == 0) # One element only!
688 {
689 scramlogmsg("\nFinding a value for $envname:","\n\n");
690 # We have an environment and only one data element:
691 # Check the lookup DB:
692 if ($tsv->checkDB($envname))
693 {
694 scramlogmsg("\tValidating value for $envname (found in tool DB):","\n");
695 if ($tsv->validatepath())
696 {
697 # Save in TSV and store in ToolData object:
698 $tsv->savevalue($envname,$tsv->pathfromdb());
699 $self->store($tooldataobj, $envname, $tsv->pathfromdb());
700 }
701 else
702 {
703 $path = $tsv->findvalue($envname, $envdata);
704 # Save the value in ToolData object:
705 $self->store($tooldataobj, $envname, $path);
706 }
707 }
708 else
709 {
710 $path = $tsv->findvalue($envname, $envdata);
711 # Save in ToolData object:
712 $self->store($tooldataobj, $envname, $path);
713 }
714 }
715 elsif ($envdata != 0 && $#$envdata > 0)
716 {
717 scramlogmsg("\nFinding a value for $envname:","\n\n");
718 foreach my $elementdata (@$envdata)
719 {
720 $path = $tsv->findvalue($envname, $elementdata);
721 # Save in ToolData object:
722 $self->store($tooldataobj, $envname, $path);
723 }
724 }
725 elsif (exists($ENV{$envname}))
726 {
727 # Nothing to do here:
728 push(@$runtime, $envname); # FIX From Shahzad.
729 next;
730 }
731 else
732 {
733 push(@$runtime, $envname);
734 }
735 }
736 # Check that the required libraries exist:
737 $self->_lib_validate($tooldataobj);
738 # Now process the runtime settings:
739 scramlogmsg("\n-------------------------------\n");
740 foreach my $rtname (@$runtime)
741 {
742 my $type = 'RUNTIME';
743 my $envdata = $tsv->environment($type, $rtname);
744 my ($rttype,$realrtname) = split(':',$rtname);
745
746 # Only validate paths:
747 if ($rtname =~ /:/)
748 {
749 # Handle single-occurrence variables first (i.e. VAR appears once
750 # in array of hashes):
751 if ($envdata != 0 && $#$envdata == 0) # One element only!
752 {
753 scramlogmsg("\nRuntime path settings for $realrtname:","\n\n");
754 # We have an environment and only one data element:
755 # Check the lookup DB:
756 if ($tsv->checkDB($rtname))
757 {
758 scramlogmsg("\tValidating value for path $realrtname (found in tool DB):","\n");
759 if ($tsv->validatepath())
760 {
761 # Save in TSV and store in ToolData object:
762 $tsv->savevalue($rtname, $tsv->pathfromdb());
763 $tooldataobj->runtime($rtname, [ $tsv->pathfromdb() ]);
764 }
765 else
766 {
767 $path = $tsv->findvalue($rtname, $envdata);
768 # Save the value in ToolData object:
769 $tooldataobj->runtime($rtname, [ $path ]);
770 }
771 }
772 else
773 {
774 $path = $tsv->findvalue($rtname, $envdata);
775 # Save in ToolData object:
776 $tooldataobj->runtime($rtname, [ $path ]);
777 }
778 }
779 elsif ($envdata != 0 && $#$envdata > 0)
780 {
781 scramlogmsg("\nRuntime path settings for $realrtname:","\n\n");
782 foreach my $elementdata (@$envdata)
783 {
784 $path = $tsv->findvalue($rtname, $elementdata);
785 # Save in ToolData object:
786 $tooldataobj->runtime($rtname, [ $path ]);
787 }
788 }
789 else
790 {
791 next;
792 }
793 }
794 else
795 {
796 # Handle runtime variables:
797 if ($envdata != 0 && $#$envdata == 0) # One element only!
798 {
799 my $value='';
800 $tsv->checkdefaults($envdata, \$value);
801 scramlogmsg("\n");
802
803 # Chck to see if the value contains a variable that should be evaluated:
804 if ($value =~ /$/)
805 {
806 # If so, find the value and substitute. This should work for all
807 # occurrences of variables because by this point (and because the ordering
808 # was established at the start) all other variables will have real values:
809 my $dvalue = $tsv->_expandvars($value);
810 $value = $dvalue;
811 }
812
813 scramlogmsg("Runtime variable ",$rtname," set to \"",$value,"\"\n");
814
815 # Store the variable setting:
816 $tooldataobj->runtime($rtname, [ $value ]);
817 }
818 else
819 {
820 next;
821 }
822 }
823 }
824
825 scramlogmsg("\n");
826 }
827
828 sub interactively_find_settings()
829 {
830 my $self=shift;
831 my ($tooldataobj, $environments, $ordering)=@_;
832 my $stringtoeval;
833 my $runtime=[];
834 my ($path, $dpath);
835
836 use BuildSystem::ToolSettingValidator;
837
838 my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname(), $self->{interactive});
839
840 foreach my $envname (@$ordering)
841 {
842 my $type = 'ENVIRONMENT';
843 my $envdata = $tsv->environment($type, $envname);
844
845 # Handle single-occurrence variables first (i.e. VAR appears once
846 # in array of hashes):
847 if ($envdata != 0 && $#$envdata == 0) # One element only!
848 {
849 print "\nFinding a value for $envname:","\n";
850 print "\n";
851 # We have an environment and only one data element:
852 # Check the lookup DB:
853 if ($tsv->checkDB($envname))
854 {
855 print "\tValidating value for $envname (found in tool DB):","\n";
856 if ($tsv->validatepath())
857 {
858 # This is our default:
859 $dpath = $tsv->pathfromdb();
860 # Run promptuser() to see if this value can be kept
861 # or should be changed:
862 $path = $tsv->promptuser($envname, $dpath);
863 # Save in TSV and store in ToolData object:
864 $tsv->savevalue($envname,$path);
865 $self->store($tooldataobj, $envname, $path);
866 }
867 else
868 {
869 $path = $tsv->ifindvalue($envname, $envdata);
870 # Save the value in ToolData object:
871 $self->store($tooldataobj, $envname, $path);
872 }
873 }
874 else
875 {
876 $dpath = $tsv->ifindvalue($envname, $envdata);
877 # Save in ToolData object:
878 $self->store($tooldataobj, $envname, $dpath);
879 }
880 }
881 elsif ($envdata != 0 && $#$envdata > 0)
882 {
883 print "\nFinding a value for $envname:","\n";
884 print "\n";
885 foreach my $elementdata (@$envdata)
886 {
887 $path = $tsv->ifindvalue($envname, $elementdata);
888 # Save in ToolData object:
889 $self->store($tooldataobj, $envname, $path);
890 }
891 }
892 elsif (exists($ENV{$envname}))
893 {
894 # Nothing to do here:
895 next;
896 }
897 else
898 {
899 push(@$runtime, $envname);
900 }
901 }
902
903 # Check that the required libraries exist:
904 $self->_lib_validate($tooldataobj);
905
906 # Now process the runtime settings:
907 print "\n";
908 print "-------------------------------\n";
909 foreach my $rtname (@$runtime)
910 {
911 my $type = 'RUNTIME';
912 my $envdata = $tsv->environment($type, $rtname);
913 my ($rttype,$realrtname) = split(':',$rtname);
914
915 # Only validate paths:
916 if ($rtname =~ /:/)
917 {
918 # Handle single-occurrence variables first (i.e. VAR appears once
919 # in array of hashes):
920 if ($envdata != 0 && $#$envdata == 0) # One element only!
921 {
922 print "\nRuntime path settings for $realrtname:","\n";
923 print "\n";
924 # We have an environment and only one data element:
925 # Check the lookup DB:
926 if ($tsv->checkDB($rtname))
927 {
928 print "\tValidating value for path $realrtname (found in tool DB):","\n";
929 if ($tsv->validatepath())
930 {
931 $dpath = $tsv->pathfromdb();
932 # Run promptuser() to see if this value can be kept
933 # or should be changed:
934 $path = $tsv->promptuser($rtname, $dpath);
935 # Save in TSV and store in ToolData object:
936 $tsv->savevalue($rtname, $path);
937 $tooldataobj->runtime($rtname, [ $path ]);
938 }
939 else
940 {
941 $dpath = $tsv->ifindvalue($rtname, $envdata);
942 # Save the value in ToolData object:
943 $tooldataobj->runtime($rtname, [ $path ]);
944 }
945 }
946 else
947 {
948 $path = $tsv->ifindvalue($rtname, $envdata);
949 # Save in ToolData object:
950 $tooldataobj->runtime($rtname, [ $path ]);
951 }
952 }
953 elsif ($envdata != 0 && $#$envdata > 0)
954 {
955 print "\nRuntime path settings for $realrtname:","\n";
956 print "\n";
957 foreach my $elementdata (@$envdata)
958 {
959 $path = $tsv->ifindvalue($rtname, $elementdata);
960 # Save in ToolData object:
961 $tooldataobj->runtime($rtname, [ $path ]);
962 }
963 }
964 else
965 {
966 next;
967 }
968 }
969 else
970 {
971 # Handle runtime variables:
972 if ($envdata != 0 && $#$envdata == 0) # One element only!
973 {
974 my $dvalue='';
975 $tsv->checkdefaults($envdata, \$dvalue);
976 print "\n";
977 my $value = $tsv->promptuserforvar($rtname, $dvalue);
978 # Store the variable setting:
979 $tooldataobj->runtime($rtname, [ $value ]);
980 }
981 else
982 {
983 next;
984 }
985 }
986 }
987
988 print "\n";
989 }
990
991 sub store()
992 {
993 my $self=shift;
994 my ($tooldataobj, $envname, $path) = @_;
995 my $subrtn = lc($envname);
996
997 if ($tooldataobj->can($subrtn))
998 {
999 $tooldataobj->$subrtn([ $path ]);
1000 }
1001 else
1002 {
1003 $tooldataobj->variable_data($envname, $path);
1004 }
1005 }
1006
1007 sub _lib_validate()
1008 {
1009 my $self=shift;
1010 my ($toolobj)=@_;
1011 my $errorstatus = { 0 => $main::good."[OK]".$main::normal, 1 => $main::error."[ERROR]".$main::normal };
1012 my $libsfound={};
1013
1014 # Firstly, we check to see if there are libraries provided by this tool:
1015 my @libraries = $toolobj->lib();
1016 my @libpaths = $toolobj->libdir();
1017
1018 foreach my $ldir (@libpaths)
1019 {
1020 my $full_libname_glob="lib".$lib."*.*";
1021 # Change to lib dir so we avoid the very long paths in our glob:
1022 chdir($ldir);
1023 # Next we use a glob to get libs matching this string (so we
1024 # can see if there's a shared or archive lib):
1025 my @possible_libs = glob($full_libname_glob);
1026 #
1027 map
1028 {
1029 $_ =~ s/\.so*|\.a*//g; # Remove all endings
1030 # Store in our hash of found libs:
1031 $libsfound->{$_} = 1;
1032 } @possible_libs;
1033 }
1034
1035 # Next we iterate over the list of libraries in our tool and
1036 # see if it was found in one of the libdirs:
1037 scramlogmsg("\n\n"), if ($#libraries != -1);
1038 foreach my $library (@libraries)
1039 {
1040 # Good status:
1041 my $errorid = 0;
1042 if (! exists ($libsfound->{'lib'.$library}))
1043 {
1044 # Check in system library dirs:
1045 if ($self->_check_system_libs($library))
1046 {
1047 $errorid = 0;
1048 }
1049 else
1050 {
1051 $errorid = 1;
1052 }
1053 }
1054 scramlogmsg(sprintf("* Library check %-10s for lib%-12s\n",$errorstatus->{$errorid}, $library));
1055 }
1056
1057 scramlogmsg("\n");
1058 }
1059
1060 sub _check_system_libs()
1061 {
1062 my $self=shift;
1063 my ($lib)=@_;
1064 my $libsfound = {};
1065 my $systemdirs = [ qw( /lib /usr/lib /usr/local/lib /usr/X11R6/lib ) ];
1066 my $full_libname_glob="lib".$lib."*.*";
1067 my $found = 0;
1068
1069 foreach my $dir (@$systemdirs)
1070 {
1071 # Change to lib dir so we avoid the very long paths in our glob:
1072 chdir($dir);
1073 # Next we use a glob to get libs matching this string (so we
1074 # can see if there's a shared or archive lib):
1075 my @possible_libs = glob($full_libname_glob);
1076 #
1077 map
1078 {
1079 $_ =~ s/\.so*|\.a*//g; # Remove all endings
1080 # Store in our hash of found libs:
1081 $libsfound->{$_} = 1;
1082 } @possible_libs;
1083 }
1084
1085 # See if we find the library in the system lib directories:
1086 if (! exists ($libsfound->{'lib'.$library}))
1087 {
1088 $found = 1;
1089 }
1090
1091 return $found;
1092 }
1093
1094 sub AUTOLOAD()
1095 {
1096 my ($xmlparser,$name,%attributes)=@_;
1097 return if $AUTOLOAD =~ /::DESTROY$/;
1098 my $name=$AUTOLOAD;
1099 $name =~ s/.*://;
1100 }
1101
1102 1;