ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolParser.pm
Revision: 1.8.2.3.2.1
Committed: Thu Mar 13 12:54:50 2008 UTC (17 years, 1 month ago) by muzaffar
Content type: text/plain
Branch: SCRAM_V2_0
CVS Tags: V2_1_1, V2_1_0, V2_0_6, V2_0_5, V2_0_4, V2_0_4_relcand2, V2_0_4_relcand1, V2_0_3, V2_0_3_relcand3, V2_0_3_relcand2, V2_0_3_relcand1, V2_0_2, V2_0_2_relcand1, V2_0_1, V2_0_1_relcand4, V2_0_1_relcand3, V2_0_1_relcand2, V2_0_1_relcand1, V2_0_0_relcand4, V2_0_0, V2_0_0_relcand3, V2_0_0_relcand2, V2_0_0_relcand1
Changes since 1.8.2.3: +7 -37 lines
Log Message:
scram v2.0 for multiple arch support and big lib stuff

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