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

# User Rev Content
1 sashby 1.2 #____________________________________________________________________
2     # File: ToolParser.pm
3     #____________________________________________________________________
4     #
5     # Author: Shaun Ashby <Shaun.Ashby@cern.ch>
6     # Update: 2004-02-09 20:14:55+0100
7 muzaffar 1.8.2.3 # Revision: $Id: ToolParser.pm,v 1.8.2.2 2008/02/15 17:30:59 muzaffar Exp $
8 sashby 1.2 #
9     # Copyright: 2004 (C) Shaun Ashby
10     #
11     #--------------------------------------------------------------------
12     package BuildSystem::ToolParser;
13     require 5.004;
14    
15     use Exporter;
16 muzaffar 1.8 use SCRAM::MsgLog;
17 sashby 1.2 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 sashby 1.6 $self={};
38 sashby 1.2
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 sashby 1.6 $self->{scramdoc}=ActiveDoc::SimpleDoc->new();
48     $self->{scramdoc}->newparse("setup", $self->{mydoctype},'Subs');
49 muzaffar 1.8.2.2 $self->{envorder}=[];
50 sashby 1.6
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 sashby 1.2 }
205    
206 sashby 1.6 sub client_()
207 sashby 1.2 {
208 sashby 1.6 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 sashby 1.2
219 sashby 1.6 $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 muzaffar 1.8.2.3 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 sashby 1.6 }
244     else
245     {
246     # No entry yet so just store the hashref:
247     $self->{"$self->{levels}->[$self->{nested}]".content}->{ENVIRONMENT}->{$envname} = [ $hashref ];
248 muzaffar 1.8.2.2 push @{$self->{envorder}},$envname;
249 sashby 1.6 }
250 sashby 1.2 }
251    
252 sashby 1.6 sub makefile()
253     {
254     my ($object,$name,%attributes)=@_;
255     }
256    
257     sub makefile_()
258     {
259 muzaffar 1.8.2.1 my ($object,$name,$cdata)=@_;
260 sashby 1.6 push(@{$self->{"$self->{levels}->[$self->{nested}]".content}->{MAKEFILE}},
261 muzaffar 1.8.2.1 join("\n",@$cdata));
262 sashby 1.6 }
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 sashby 1.2 sub parse
306     {
307     my $self=shift;
308 sashby 1.6 my ($tool,$toolver,$file)=@_;
309 sashby 1.2 $self->{tool}=$tool;
310     $self->{version}=$toolver;
311 sashby 1.6 $self->{scramdoc}->filetoparse($file);
312 sashby 1.2 $self->verbose("Setup Parse");
313 muzaffar 1.7 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 sashby 1.6 delete $self->{scramdoc};
317 sashby 1.2 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 sashby 1.4
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 muzaffar 1.8.2.3
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 sashby 1.2 if ($self->{interactive})
654     {
655     # Set the values interactively:
656 muzaffar 1.8.2.3 $self->interactively_find_settings($tooldataobj, $environments, \@order);
657 sashby 1.2 }
658     else
659     {
660     # Set the values:
661 muzaffar 1.8.2.3 $self->find_settings($tooldataobj, $environments, \@order);
662 sashby 1.2 }
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 muzaffar 1.8 scramlogmsg("\nFinding a value for $envname:","\n\n");
690 sashby 1.2 # We have an environment and only one data element:
691     # Check the lookup DB:
692     if ($tsv->checkDB($envname))
693     {
694 muzaffar 1.8 scramlogmsg("\tValidating value for $envname (found in tool DB):","\n");
695 sashby 1.2 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 muzaffar 1.8 scramlogmsg("\nFinding a value for $envname:","\n\n");
718 sashby 1.2 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 sashby 1.5 push(@$runtime, $envname); # FIX From Shahzad.
729 sashby 1.2 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 muzaffar 1.8 scramlogmsg("\n-------------------------------\n");
740 sashby 1.2 foreach my $rtname (@$runtime)
741     {
742     my $type = 'RUNTIME';
743     my $envdata = $tsv->environment($type, $rtname);
744     my ($rttype,$realrtname) = split(':',$rtname);
745 sashby 1.3
746 sashby 1.2 # 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 muzaffar 1.8 scramlogmsg("\nRuntime path settings for $realrtname:","\n\n");
754 sashby 1.2 # We have an environment and only one data element:
755     # Check the lookup DB:
756     if ($tsv->checkDB($rtname))
757     {
758 muzaffar 1.8 scramlogmsg("\tValidating value for path $realrtname (found in tool DB):","\n");
759 sashby 1.2 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 muzaffar 1.8 scramlogmsg("\nRuntime path settings for $realrtname:","\n\n");
782 sashby 1.2 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 muzaffar 1.8 scramlogmsg("\n");
802 sashby 1.2
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 muzaffar 1.8 scramlogmsg("Runtime variable ",$rtname," set to \"",$value,"\"\n");
814 sashby 1.2
815     # Store the variable setting:
816     $tooldataobj->runtime($rtname, [ $value ]);
817     }
818     else
819     {
820     next;
821     }
822     }
823     }
824    
825 muzaffar 1.8 scramlogmsg("\n");
826 sashby 1.2 }
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 muzaffar 1.8 scramlogmsg("\n\n"), if ($#libraries != -1);
1038 sashby 1.2 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 muzaffar 1.8 scramlogmsg(sprintf("* Library check %-10s for lib%-12s\n",$errorstatus->{$errorid}, $library));
1055 sashby 1.2 }
1056    
1057 muzaffar 1.8 scramlogmsg("\n");
1058 sashby 1.2 }
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 sashby 1.6 sub AUTOLOAD()
1095     {
1096     my ($xmlparser,$name,%attributes)=@_;
1097     return if $AUTOLOAD =~ /::DESTROY$/;
1098     my $name=$AUTOLOAD;
1099     $name =~ s/.*://;
1100     }
1101    
1102 sashby 1.2 1;