ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolParser.pm
Revision: 1.8.2.2
Committed: Fri Feb 15 17:30:59 2008 UTC (17 years, 2 months ago) by muzaffar
Content type: text/plain
Branch: forBinLess_SCRAM
CVS Tags: V1_2_0-cand2
Changes since 1.8.2.1: +6 -38 lines
Log Message:
more cleanup. no more http: protocol used. So no more extra dependency on libwww and uri perl modules

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