ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolParser.pm
Revision: 1.8.2.1
Committed: Fri Feb 15 14:58:01 2008 UTC (17 years, 2 months ago) by muzaffar
Content type: text/plain
Branch: forBinLess_SCRAM
CVS Tags: V1_2_0-cand1
Changes since 1.8: +3 -16 lines
Log Message:
binary independent scram in forBinLess_SCRAM branch

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