ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/XMLToolParser.pm
Revision: 1.1
Committed: Tue Jul 26 15:14:00 2005 UTC (19 years, 9 months ago) by sashby
Content type: text/plain
Branch: MAIN
CVS Tags: V1_0_4p1, V1_0_2, V1_0_2_p1
Branch point for: v103_branch
Log Message:
Added XML version of ToolParser classes. Started to add support for upgrade mode of project command

File Contents

# User Rev Content
1 sashby 1.1 #____________________________________________________________________
2     # File: XMLToolParser.pm
3     #____________________________________________________________________
4     #
5     # Author: Shaun Ashby <Shaun.Ashby@cern.ch>
6     # Update: 2005-04-22 15:22:06+0200
7     # Revision: $Id: XMLToolParser.pm,v 1.2 2005/04/29 16:18:56 sashby Exp $
8     #
9     # Copyright: 2005 (C) Shaun Ashby
10     #
11     #--------------------------------------------------------------------
12     package BuildSystem::XMLToolParser;
13     require 5.004;
14     use Exporter;
15     use BuildSystem::XMLToolTagUtils;
16     use ActiveDoc::SimpleXMLDoc;
17     use Utilities::Verbose;
18    
19     @ISA=qw(Exporter Utilities::Verbose);
20     @EXPORT_OK=qw( );
21    
22     #
23     sub new()
24     ###############################################################
25     # new #
26     ###############################################################
27     # modified : Wed Dec 3 19:03:22 2003 / SFA #
28     # params : #
29     # : #
30     # function : #
31     # : #
32     ###############################################################
33     {
34     my $proto=shift;
35     my $class=ref($proto) || $proto;
36     my $self={};
37    
38     bless $self,$class;
39    
40     $self->{cache}=shift;
41     $self->{mydoctype}="BuildSystem::XMLToolParser";
42     $self->{mydocversion}="1.1";
43     $self->{interactive} = 0;
44     $self->{content} = {};
45     $self->{nested} = 0;
46     return $self;
47     }
48    
49     sub _parser()
50     {
51     my $self=shift;
52    
53     # Initialise the doc and a XML::Parser instance, passing in
54     # the default handlers for start, end and char types:
55     $self->{simplexmldoc} = ActiveDoc::SimpleXMLDoc->new(\&BuildSystem::XMLToolTagUtils::OpenTagHandler,
56     \&BuildSystem::XMLToolTagUtils::ClosingTagHandler,
57     \&BuildSystem::XMLToolTagUtils::CharHandler,
58     "setup");
59    
60     # Pass a ref to parent object so that tag data can be stored
61     # directly in the XMLToolParser object:
62     &BuildSystem::XMLToolTagUtils::datastore($self);
63    
64     # Register the specific tag routines with expected attributes. If no checking should be done
65     # then just put 0. For nested tags, last element is 1:
66     $self->{simplexmldoc}->registerTag("setup",
67     "use",
68     \&BuildSystem::XMLToolTagUtils::usetaghandler,
69     [ "name" ],
70     0);
71    
72     $self->{simplexmldoc}->registerTag("setup",
73     "lib",
74     \&BuildSystem::XMLToolTagUtils::libtaghandler,
75     [ "name" ],
76     0);
77    
78     $self->{simplexmldoc}->registerTag("setup",
79     "info",
80     \&BuildSystem::XMLToolTagUtils::infotaghandler,
81     [ "url" ],
82     0);
83    
84     $self->{simplexmldoc}->registerTag("setup",
85     "flags",
86     \&BuildSystem::XMLToolTagUtils::flagstaghandler,
87     0,
88     0);
89    
90     $self->{simplexmldoc}->registerTag("setup",
91     "environment",
92     \&BuildSystem::XMLToolTagUtils::environmenttaghandler,
93     [ "name" ],
94     0);
95    
96     $self->{simplexmldoc}->registerTag("setup",
97     "runtime",
98     \&BuildSystem::XMLToolTagUtils::runtimetaghandler,
99     [ "name" ],
100     0);
101    
102     $self->{simplexmldoc}->registerTag("setup",
103     "makefile",
104     \&BuildSystem::XMLToolTagUtils::makefiletaghandler,
105     0,
106     1);
107    
108     # Nested tags (i.e. tags that can contain other tags):
109     $self->{simplexmldoc}->registerTag("setup",
110     "client",
111     \&BuildSystem::XMLToolTagUtils::clienttaghandler,
112     0,
113     1);
114    
115     $self->{simplexmldoc}->registerTag("setup",
116     "architecture",
117     \&BuildSystem::XMLToolTagUtils::archtaghandler,
118     [ "name" ],
119     1);
120     # The main tool handler:
121     $self->{simplexmldoc}->registerTag("setup",
122     "tool",
123     \&BuildSystem::XMLToolTagUtils::tooltaghandler,
124     [ "name", "version" ],
125     1);
126    
127     # Register the XML parsing tag routines (default ones, plus those added above):
128     $self->{simplexmldoc}->setHandlers();
129    
130     # Return the parser object:
131     return $self->{simplexmldoc};
132     }
133    
134     sub simplexmldoc()
135     {
136     my $self=shift;
137     @_ ? $self->{simplexmldoc} = shift
138     : $self->{simplexmldoc};
139     }
140    
141     sub parse()
142     {
143     my $self=shift;
144     my ($tool,$toolver,$file)=@_;
145     $self->{tool}=$tool;
146     $self->{version}=$toolver;
147     $self->verbose("Setup Parse");
148     # Parse the file:
149     $self->_parser()->parsefile($file);
150     # We're done with the simpleXMLDoc object:
151     delete $self->{simplexmldoc};
152     }
153    
154     sub pushlevel
155     {
156     my $self = shift;
157     my ($info, $nextlevel)=@_;
158    
159     $self->{id} = $info if (defined $info);
160    
161     # Check to see if last tag was arch: if so, ceate new level:
162     if ($self->{isarch} == 1)
163     {
164     $self->{nested} = 2;
165     $self->{nexttagcontent}={};
166     }
167     else
168     {
169     $self->{nested} = 1;
170     $self->{tagcontent}={};
171     }
172    
173     # Set something which says "last starter tag was ARCH":
174     if ($nextlevel)
175     {
176     $self->{isarch} = 1;
177     }
178     }
179    
180     sub poplevel
181     {
182     my $self = shift;
183    
184     # Drop level of nesting by one:
185     $self->{nested}--;
186    
187     if ($self->{isarch} != 1)
188     {
189     delete $self->{tagcontent};
190     }
191     }
192    
193     sub rmenvdata
194     {
195     my $self=shift;
196     delete $self->{ENVDATA};
197     }
198    
199     ###################################
200     ## Data Access Methods ##
201     ###################################
202     sub toolname
203     {
204     my $self=shift;
205     # Return tool name:
206     return ($self->{content}->{TOOLNAME});
207     }
208    
209     sub toolversion
210     {
211     my $self=shift;
212     # Return tool version:
213     return ($self->{content}->{TOOLVERSION});
214     }
215    
216     sub toolcontent
217     {
218     my $self=shift;
219     # Return whole of content hash:
220     return $self->{content};
221     }
222    
223     sub getrawdata()
224     {
225     my $self=shift;
226     my ($tagtype)=@_;
227    
228     # Check to see if we have data for this tag:
229     if (! exists ($self->{content}->{$tagtype}))
230     {
231     # If not, return:
232     return 0;
233     }
234    
235     # Check the number of keys for hash referred to by this object.
236     # If 0, return:
237     if (ref($self->{content}->{$tagtype}) eq 'HASH') #
238     {
239     if ((my $nkeys=keys %{$self->{content}->{$tagtype}}) > 0)
240     {
241     # Return the data for the tag $tagtype. ARCH is a bit special because
242     # we want the data for the actual arch (thus, data is on a different level):
243     if ($tagtype eq 'ARCH')
244     {
245     my $archmatch = {};
246     # Check for matching arch key and return hash of relevant data.
247     # Also must take into account the fact that several arch names may match, e.g. Linux, Linux__2 and
248     # Linux__2.4 all match. If we find more than one match, collect ALL matching data and return it:
249     while (my ($k,$v) = each %{$self->{content}->{ARCH}})
250     {
251     # For every matching architecture we snatch the data and squirrel it away:
252     if ( $ENV{SCRAM_ARCH} =~ /$k.*/ )
253     {
254     # Now we check the tags inside the arch block. Note that we do not want to descend
255     # into CLIENT tags, if these exist. We just want to return all data in the ARCH
256     # block while making sure that multiple matches are handled correctly. We assume that
257     # you will only find one CLIENT block inside and ARCH:
258     while (my ($matchtag, $matchval) = each %{$v})
259     {
260     if ($matchtag =~ /CLIENT|FLAGS|RUNTIME/)
261     {
262     $archmatch->{$matchtag} = $matchval;
263     }
264     else
265     {
266     # Treat tags differently according to whether they are HASHes or ARRAYs:
267     if (ref($matchval) =~ /HASH/)
268     {
269     while (my ($t, $val) = each %{$matchval})
270     {
271     if (exists ($archmatch->{$matchtag}->{$t}))
272     {
273     push(@{$archmatch->{$matchtag}->{$t}},@$val);
274     }
275     else
276     {
277     $archmatch->{$matchtag}->{$t} = $val;
278     }
279     }
280     }
281     else # Here we deal with arrays:
282     {
283     if (exists ($archmatch->{$matchtag}))
284     {
285     push(@{$archmatch->{$matchtag}},@$matchval);
286     }
287     else
288     {
289     $archmatch->{$matchtag} = $matchval;
290     }
291     }
292     }
293     }
294     }
295     }
296     # Return the squirrel:
297     return $archmatch;
298    
299     } # End of ARCH tag treatment
300     else
301     {
302     # Return other tag data:
303     return $self->{content}->{$tagtype};
304     }
305     }
306     else
307     {
308     print "Warning: $tagtype tags contain no other tag data!","\n";
309     return undef;
310     }
311     }
312     else
313     {
314     # We have an array of data or a scalar:
315     return $self->{content}->{$tagtype};
316     }
317     }
318    
319     sub processrawtool()
320     {
321     my $self=shift;
322     my ($interactive) = @_;
323     my $data = [];
324     my $environments = {}; # Somewhere to collect our environments
325    
326     # Set interactive mode if required:
327     $self->{interactive} = $interactive;
328    
329     # Somewhere to store the data:
330     use BuildSystem::ToolData;
331     my $tooldataobj = BuildSystem::ToolData->new();
332    
333     # Set the name and version:
334     $tooldataobj->toolname($self->toolname());
335     $tooldataobj->toolversion($self->toolversion());
336    
337     # First, collect all tag data so that we only have non-nested tags.
338     # Check for architecture-dependent data first, followed by client tags:
339     foreach $nested_tag (qw( ARCH CLIENT ))
340     {
341     if (my $thisdata=$self->getrawdata($nested_tag))
342     {
343     foreach my $item (keys %{ $thisdata })
344     {
345     if ($item eq 'CLIENT')
346     {
347     my $clientdata = $thisdata->{$item};
348     foreach my $ckey (keys %{$clientdata})
349     {
350     $environments->{$ckey} = $clientdata->{$ckey};
351     }
352     }
353     elsif ($item eq 'ENVIRONMENT' || $item eq 'RUNTIME')
354     {
355     # Check to see if tag already exists before saving:
356     if (exists($environments->{$item}))
357     {
358     foreach my $ek (keys %{$thisdata})
359     {
360     if (exists($environments->{$item}->{$ek}))
361     {
362     push(@{$environments->{$item}->{$ek}}, @{$thisdata->{$item}->{$ek}});
363     }
364     else
365     {
366     $environments->{$item}->{$ek} = $thisdata->{$item}->{$ek};
367     }
368     }
369     }
370     else
371     {
372     # There isn't an entry yet:
373     $environments->{$item} = $thisdata->{$item};
374     }
375     }
376     else
377     {
378     my $data = $thisdata->{$item};
379    
380     if (ref($data) eq 'HASH')
381     {
382     while (my ($f,$v) = each %$data)
383     {
384     $tooldataobj->flags($f,$v);
385     }
386     }
387     else
388     {
389     my $subname = lc($item);
390     $tooldataobj->$subname($data), if ($#$data != -1);
391     }
392     }
393     }
394     }
395     else
396     {
397     # No entry for this nested tag. Proceed.
398     next;
399     }
400     }
401    
402     # Now handle all other normal tags:
403     foreach my $normal_tag (qw( ENVIRONMENT RUNTIME ))
404     {
405     # Do we have some data for this tag?
406     if (my $thisdata=$self->getrawdata($normal_tag))
407     {
408     # Add the data to our environments hash. We must check to see if
409     # there is an entry already:
410     if (exists($environments->{$normal_tag}))
411     {
412     foreach my $ek (keys %{$thisdata})
413     {
414     if (exists($environments->{$normal_tag}->{$ek}))
415     {
416     push(@{$environments->{$normal_tag}->{$ek}}, @{$thisdata->{$normal_tag}->{$ek}});
417     }
418     else
419     {
420     $environments->{$normal_tag}->{$ek} = $thisdata->{$normal_tag}->{$ek};
421     }
422     }
423     }
424     else
425     {
426     # There isn't an entry yet:
427     $environments->{$normal_tag} = $thisdata;
428     }
429     }
430     else
431     {
432     # No data so proceed:
433     next;
434     }
435     }
436    
437     # Finally, tags that can be stored straight away:
438     foreach my $tag (qw( FLAGS MAKEFILE ))
439     {
440     my $bdata = $self->getrawdata($tag);
441     if (ref($bdata) eq 'HASH')
442     {
443     while (my ($f,$v) = each %$bdata)
444     {
445     $tooldataobj->flags($f,$v);
446     }
447     }
448     else
449     {
450     $tooldataobj->makefile($bdata), if ($#$bdata != -1);
451     }
452     }
453    
454     # Libs and tool dependencise:
455     foreach my $tag (qw( LIB USE ))
456     {
457     my $bdata = $self->getrawdata($tag);
458     my $subname = lc($tag);
459     $tooldataobj->$subname($bdata), if ($#$bdata != -1);
460     }
461    
462     # Also check to see if this tool is a scram-managed project. If
463     # so, set the SCRAM_PROJECT variable in the ToolData object:
464     if (exists ($self->{content}->{SCRAM_PROJECT}))
465     {
466     $tooldataobj->scram_project($self->{content}->{SCRAM_PROJECT});
467     }
468    
469     # And check to see if this tool is a compiler. If so, set
470     # the SCRAM_COMPILER variable in the ToolData object:
471     if (exists ($self->{content}->{SCRAM_COMPILER}))
472     {
473     $tooldataobj->scram_compiler($self->{content}->{SCRAM_COMPILER});
474     }
475    
476     # Establish the order of parsing the value strings:
477     my $order = $self->process_environments($environments);
478    
479     if ($self->{interactive})
480     {
481     # Set the values interactively:
482     $self->interactively_find_settings($tooldataobj, $environments, $order);
483     }
484     else
485     {
486     # Set the values:
487     $self->find_settings($tooldataobj, $environments, $order);
488     }
489    
490     # Return a ToolData object:
491     return $tooldataobj;
492     }
493    
494     sub process_environments()
495     {
496     my $self=shift;
497     my ($environments)=@_;
498    
499     use BuildSystem::SCRAMGrapher;
500     my $G = BuildSystem::SCRAMGrapher->new();
501    
502     foreach $envtype (keys %{$environments})
503     {
504     while (my ($envcontent,$envdata) = each %{$environments->{$envtype}})
505     {
506     # Add a vertex for the VARIABLE name:
507     $G->vertex($envcontent);
508    
509     foreach my $element (@$envdata)
510     {
511     if (exists($element->{'ELEMENTS'}))
512     {
513     map
514     {
515     # Add a path for each element in ELEMENTS:
516     $G->edge($envcontent, $_);
517     } @{$element->{'ELEMENTS'}};
518     }
519     }
520     }
521     }
522    
523     my $setup_order = $G->sort();
524     return $setup_order;
525     }
526    
527     sub find_settings()
528     {
529     my $self=shift;
530     my ($tooldataobj, $environments, $ordering)=@_;
531     my $stringtoeval;
532     my $runtime=[];
533     my $path;
534    
535     use BuildSystem::ToolSettingValidator;
536    
537     my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname());
538    
539     foreach my $envname (@$ordering)
540     {
541     my $type = 'ENVIRONMENT';
542     my $envdata = $tsv->environment($type, $envname);
543    
544     # Handle single-occurrence variables first (i.e. VAR appears once
545     # in array of hashes):
546     if ($envdata != 0 && $#$envdata == 0) # One element only!
547     {
548     print "\nFinding a value for $envname:","\n";
549     print "\n";
550     # We have an environment and only one data element:
551     # Check the lookup DB:
552     if ($tsv->checkDB($envname))
553     {
554     print "\tValidating value for $envname (found in tool DB):","\n";
555     if ($tsv->validatepath())
556     {
557     # Save in TSV and store in ToolData object:
558     $tsv->savevalue($envname,$tsv->pathfromdb());
559     $self->store($tooldataobj, $envname, $tsv->pathfromdb());
560     }
561     else
562     {
563     $path = $tsv->findvalue($envname, $envdata);
564     # Save the value in ToolData object:
565     $self->store($tooldataobj, $envname, $path);
566     }
567     }
568     else
569     {
570     $path = $tsv->findvalue($envname, $envdata);
571     # Save in ToolData object:
572     $self->store($tooldataobj, $envname, $path);
573     }
574     }
575     elsif ($envdata != 0 && $#$envdata > 0)
576     {
577     print "\nFinding a value for $envname:","\n";
578     print "\n";
579     foreach my $elementdata (@$envdata)
580     {
581     $path = $tsv->findvalue($envname, $elementdata);
582     # Save in ToolData object:
583     $self->store($tooldataobj, $envname, $path);
584     }
585     }
586     elsif (exists($ENV{$envname}))
587     {
588     # Nothing to do here:
589     next;
590     }
591     else
592     {
593     push(@$runtime, $envname);
594     }
595     }
596    
597     # Check that the required libraries exist:
598     $self->_lib_validate($tooldataobj);
599    
600     # Now process the runtime settings:
601     print "\n";
602     print "-------------------------------\n";
603    
604     foreach my $rtname (@$runtime)
605     {
606     my $type = 'RUNTIME';
607     my $envdata = $tsv->environment($type, $rtname);
608     my ($rttype,$realrtname) = split(':',$rtname);
609    
610     # Only validate paths:
611     if ($rtname =~ /:/)
612     {
613     # Handle single-occurrence variables first (i.e. VAR appears once
614     # in array of hashes):
615     if ($envdata != 0 && $#$envdata == 0) # One element only!
616     {
617     print "\nRuntime path settings for $realrtname:","\n";
618     print "\n";
619     # We have an environment and only one data element:
620     # Check the lookup DB:
621     if ($tsv->checkDB($rtname))
622     {
623     print "\tValidating value for path $realrtname (found in tool DB):","\n";
624     if ($tsv->validatepath())
625     {
626     # Save in TSV and store in ToolData object:
627     $tsv->savevalue($rtname, $tsv->pathfromdb());
628     $tooldataobj->runtime($rtname, [ $tsv->pathfromdb() ]);
629     }
630     else
631     {
632     $path = $tsv->findvalue($rtname, $envdata);
633     # Save the value in ToolData object:
634     $tooldataobj->runtime($rtname, [ $path ]);
635     }
636     }
637     else
638     {
639     $path = $tsv->findvalue($rtname, $envdata);
640     # Save in ToolData object:
641     $tooldataobj->runtime($rtname, [ $path ]);
642     }
643     }
644     elsif ($envdata != 0 && $#$envdata > 0)
645     {
646     print "\nRuntime path settings for $realrtname:","\n";
647     print "\n";
648     foreach my $elementdata (@$envdata)
649     {
650     $path = $tsv->findvalue($rtname, $elementdata);
651     # Save in ToolData object:
652     $tooldataobj->runtime($rtname, [ $path ]);
653     }
654     }
655     else
656     {
657     next;
658     }
659     }
660     else
661     {
662     # Handle runtime variables:
663     if ($envdata != 0 && $#$envdata == 0) # One element only!
664     {
665     my $value='';
666     $tsv->checkdefaults($envdata, \$value);
667     print "\n";
668    
669     # Chck to see if the value contains a variable that should be evaluated:
670     if ($value =~ /$/)
671     {
672     # If so, find the value and substitute. This should work for all
673     # occurrences of variables because by this point (and because the ordering
674     # was established at the start) all other variables will have real values:
675     my $dvalue = $tsv->_expandvars($value);
676     $value = $dvalue;
677     }
678    
679     print "Runtime variable ",$rtname," set to \"",$value,"\"\n";
680    
681     # Store the variable setting:
682     $tooldataobj->runtime($rtname, [ $value ]);
683     }
684     else
685     {
686     next;
687     }
688     }
689     }
690    
691     print "\n";
692     }
693    
694     sub interactively_find_settings()
695     {
696     my $self=shift;
697     my ($tooldataobj, $environments, $ordering)=@_;
698     my $stringtoeval;
699     my $runtime=[];
700     my ($path, $dpath);
701    
702     use BuildSystem::ToolSettingValidator;
703    
704     my $tsv = BuildSystem::ToolSettingValidator->new($environments, $self->toolname(), $self->{interactive});
705    
706     foreach my $envname (@$ordering)
707     {
708     my $type = 'ENVIRONMENT';
709     my $envdata = $tsv->environment($type, $envname);
710    
711     # Handle single-occurrence variables first (i.e. VAR appears once
712     # in array of hashes):
713     if ($envdata != 0 && $#$envdata == 0) # One element only!
714     {
715     print "\nFinding a value for $envname:","\n";
716     print "\n";
717     # We have an environment and only one data element:
718     # Check the lookup DB:
719     if ($tsv->checkDB($envname))
720     {
721     print "\tValidating value for $envname (found in tool DB):","\n";
722     if ($tsv->validatepath())
723     {
724     # This is our default:
725     $dpath = $tsv->pathfromdb();
726     # Run promptuser() to see if this value can be kept
727     # or should be changed:
728     $path = $tsv->promptuser($envname, $dpath);
729     # Save in TSV and store in ToolData object:
730     $tsv->savevalue($envname,$path);
731     $self->store($tooldataobj, $envname, $path);
732     }
733     else
734     {
735     $path = $tsv->ifindvalue($envname, $envdata);
736     # Save the value in ToolData object:
737     $self->store($tooldataobj, $envname, $path);
738     }
739     }
740     else
741     {
742     $dpath = $tsv->ifindvalue($envname, $envdata);
743     # Save in ToolData object:
744     $self->store($tooldataobj, $envname, $dpath);
745     }
746     }
747     elsif ($envdata != 0 && $#$envdata > 0)
748     {
749     print "\nFinding a value for $envname:","\n";
750     print "\n";
751     foreach my $elementdata (@$envdata)
752     {
753     $path = $tsv->ifindvalue($envname, $elementdata);
754     # Save in ToolData object:
755     $self->store($tooldataobj, $envname, $path);
756     }
757     }
758     elsif (exists($ENV{$envname}))
759     {
760     # Nothing to do here:
761     next;
762     }
763     else
764     {
765     push(@$runtime, $envname);
766     }
767     }
768    
769     # Check that the required libraries exist:
770     $self->_lib_validate($tooldataobj);
771    
772     # Now process the runtime settings:
773     print "\n";
774     print "-------------------------------\n";
775     foreach my $rtname (@$runtime)
776     {
777     my $type = 'RUNTIME';
778     my $envdata = $tsv->environment($type, $rtname);
779     my ($rttype,$realrtname) = split(':',$rtname);
780    
781     # Only validate paths:
782     if ($rtname =~ /:/)
783     {
784     # Handle single-occurrence variables first (i.e. VAR appears once
785     # in array of hashes):
786     if ($envdata != 0 && $#$envdata == 0) # One element only!
787     {
788     print "\nRuntime path settings for $realrtname:","\n";
789     print "\n";
790     # We have an environment and only one data element:
791     # Check the lookup DB:
792     if ($tsv->checkDB($rtname))
793     {
794     print "\tValidating value for path $realrtname (found in tool DB):","\n";
795     if ($tsv->validatepath())
796     {
797     $dpath = $tsv->pathfromdb();
798     # Run promptuser() to see if this value can be kept
799     # or should be changed:
800     $path = $tsv->promptuser($rtname, $dpath);
801     # Save in TSV and store in ToolData object:
802     $tsv->savevalue($rtname, $path);
803     $tooldataobj->runtime($rtname, [ $path ]);
804     }
805     else
806     {
807     $dpath = $tsv->ifindvalue($rtname, $envdata);
808     # Save the value in ToolData object:
809     $tooldataobj->runtime($rtname, [ $path ]);
810     }
811     }
812     else
813     {
814     $path = $tsv->ifindvalue($rtname, $envdata);
815     # Save in ToolData object:
816     $tooldataobj->runtime($rtname, [ $path ]);
817     }
818     }
819     elsif ($envdata != 0 && $#$envdata > 0)
820     {
821     print "\nRuntime path settings for $realrtname:","\n";
822     print "\n";
823     foreach my $elementdata (@$envdata)
824     {
825     $path = $tsv->ifindvalue($rtname, $elementdata);
826     # Save in ToolData object:
827     $tooldataobj->runtime($rtname, [ $path ]);
828     }
829     }
830     else
831     {
832     next;
833     }
834     }
835     else
836     {
837     # Handle runtime variables:
838     if ($envdata != 0 && $#$envdata == 0) # One element only!
839     {
840     my $dvalue='';
841     $tsv->checkdefaults($envdata, \$dvalue);
842     print "\n";
843     my $value = $tsv->promptuserforvar($rtname, $dvalue);
844     # Store the variable setting:
845     $tooldataobj->runtime($rtname, [ $value ]);
846     }
847     else
848     {
849     next;
850     }
851     }
852     }
853    
854     print "\n";
855     }
856    
857     sub store()
858     {
859     my $self=shift;
860     my ($tooldataobj, $envname, $path) = @_;
861     my $subrtn = lc($envname);
862    
863     if ($tooldataobj->can($subrtn))
864     {
865     $tooldataobj->$subrtn([ $path ]);
866     }
867     else
868     {
869     $tooldataobj->variable_data($envname, $path);
870     }
871     }
872    
873     sub _lib_validate()
874     {
875     my $self=shift;
876     my ($toolobj)=@_;
877     my $errorstatus = { 0 => $main::good."[OK]".$main::normal, 1 => $main::error."[ERROR]".$main::normal };
878     my $libsfound={};
879    
880     # Firstly, we check to see if there are libraries provided by this tool:
881     my @libraries = $toolobj->lib();
882     my @libpaths = $toolobj->libdir();
883    
884     foreach my $ldir (@libpaths)
885     {
886     my $full_libname_glob="lib".$lib."*.*";
887     # Change to lib dir so we avoid the very long paths in our glob:
888     chdir($ldir);
889     # Next we use a glob to get libs matching this string (so we
890     # can see if there's a shared or archive lib):
891     my @possible_libs = glob($full_libname_glob);
892     #
893     map
894     {
895     $_ =~ s/\.so*|\.a*//g; # Remove all endings
896     # Store in our hash of found libs:
897     $libsfound->{$_} = 1;
898     } @possible_libs;
899     }
900    
901     # Next we iterate over the list of libraries in our tool and
902     # see if it was found in one of the libdirs:
903     print "\n\n", if ($#libraries != -1);
904     foreach my $library (@libraries)
905     {
906     # Good status:
907     my $errorid = 0;
908     if (! exists ($libsfound->{'lib'.$library}))
909     {
910     # Check in system library dirs:
911     if ($self->_check_system_libs($library))
912     {
913     $errorid = 0;
914     }
915     else
916     {
917     $errorid = 1;
918     }
919     }
920     printf("* Library check %-10s for lib%-12s\n",$errorstatus->{$errorid}, $library);
921     }
922    
923     print "\n";
924     }
925    
926     sub _check_system_libs()
927     {
928     my $self=shift;
929     my ($lib)=@_;
930     my $libsfound = {};
931     my $systemdirs = [ qw( /lib /usr/lib /usr/local/lib /usr/X11R6/lib ) ];
932     my $full_libname_glob="lib".$lib."*.*";
933     my $found = 0;
934    
935     foreach my $dir (@$systemdirs)
936     {
937     # Change to lib dir so we avoid the very long paths in our glob:
938     chdir($dir);
939     # Next we use a glob to get libs matching this string (so we
940     # can see if there's a shared or archive lib):
941     my @possible_libs = glob($full_libname_glob);
942     #
943     map
944     {
945     $_ =~ s/\.so*|\.a*//g; # Remove all endings
946     # Store in our hash of found libs:
947     $libsfound->{$_} = 1;
948     } @possible_libs;
949     }
950    
951     # See if we find the library in the system lib directories:
952     if (! exists ($libsfound->{'lib'.$library}))
953     {
954     $found = 1;
955     }
956    
957     return $found;
958     }
959    
960     1;