ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/XMLToolParser.pm
Revision: 1.2
Committed: Fri Nov 11 19:23:59 2005 UTC (19 years, 5 months ago) by sashby
Content type: text/plain
Branch: MAIN
Changes since 1.1: +7 -4 lines
Log Message:
*** empty log message ***

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