File Coverage

blib/lib/Astro/IRAF/CL.pm
Criterion Covered Total %
statement 30 469 6.4
branch 0 140 0.0
condition 0 80 0.0
subroutine 10 59 16.9
pod 0 25 0.0
total 40 773 5.1


line stmt bran cond sub pod time code
1             package Astro::IRAF::CL;
2 1     1   6104 use strict;
  1         2  
  1         30  
3 1     1   4 use warnings;
  1         2  
  1         50  
4              
5             $SIG{INT} = sub {die}; # Without this DESTROY() does not get called
6             # when ctrl-c is used for some reason.
7              
8 1     1   4 use Carp;
  1         5  
  1         62  
9 1     1   4 use vars qw($VERSION $AUTOLOAD $TIMEOUT);
  1         2  
  1         65  
10              
11             $VERSION = '0.2.0';
12              
13 1     1   4 use Fcntl qw(:DEFAULT);
  1         2  
  1         515  
14              
15 1     1   6 use Cwd;
  1         2  
  1         76  
16 1     1   1372 use Expect 1.15;
  1         69631  
  1         85  
17 1     1   1522 use Env qw(IRAF_START);
  1         3044  
  1         5  
18              
19             my $DEBUG = 0;
20              
21             $Expect::Debug=$DEBUG;
22             $Expect::Exp_Internal=$DEBUG;
23             $Expect::Log_Stdout=$DEBUG;
24              
25             $TIMEOUT = 10; # Time out for internal commands (seconds).
26              
27             sub new{
28 0     0 0   my ($class,%params) = @_;
29              
30 0           my $self = bless {}, $class;
31              
32 0           $self->{'start_params'} = \%params; #Need this to allow restart post-crash
33              
34 0   0       $self->{'iraf_start'} = $params{'iraf_start'}||$self->_get_iraf_start();
35              
36 0   0       $self->{'debug'} = $params{'debug'} || 0;
37 0   0       $self->{'work_dir'} = $params{'work_dir'} || cwd;
38 0   0       $self->{'log'} = $params{'log'} || *STDERR;
39 0   0       $self->{'display_startup'} = $params{'display_startup'} || 0;
40              
41 0           $self->{'cl_prompt'} = qr/^cl>\s+/;
42 0           $self->{'continue_prompt'} = qr/>>>\s+/;
43              
44 0           $self->{'packages'} = []; # For loading/unloading packages.
45 0           $self->{'command_history'} = [];
46 0           $self->{'dead'} = 1; # It is dead until the CL is running.
47              
48 0           $self->{'session'} = $self->_startup;
49              
50 0           $self->_get_available_commands_and_packages('main');
51              
52 0 0         if (exists $params{'packages'}){
53 0           foreach my $package (@{$params{'packages'}}){
  0            
54 0           $self->load_package($package);
55             }
56             }
57              
58 0 0         if (exists $params{'set'}){
59 0           $self->set(%{$params{'set'}});
  0            
60             }
61              
62 0           return $self;
63             }
64              
65             sub _get_iraf_start{
66 0     0     my $self = shift @_;
67              
68 0           my $startdir;
69              
70 0 0         if (defined $IRAF_START){ # If a user has an odd place for their IRAF
71 0           $startdir = $IRAF_START; # base directory then they should use this
72             # environment variable to say so.
73             }
74             else{
75              
76             # Make educated guesses as to where the IRAF login.cl might be hiding.
77              
78             # If you have any other alternatives you could add them in here
79             # This is only really for general places rather than unique odd places
80             # though, use IRAF_START or the uparm parameter for those.
81              
82 0           my $found = 0;
83              
84 1     1   477 use Env qw(USER HOME);
  1         2  
  1         5  
85              
86 0   0       my $username = getlogin() || getpwuid($<) || $USER || `whoami`;
87              
88 0           foreach ($HOME,"$HOME/iraf","/home/$username/iraf","/home/$username") {
89              
90 0 0 0       if (-e "$_/login.cl" && -d "$_/uparm/"){
91 0           $startdir = $_;
92 0           $found = 1;
93 0           last;
94             }
95             }
96              
97 0 0         croak "Do not know where to start IRAF from" if !$found;
98             }
99              
100 0           return $startdir;
101             }
102              
103             sub _lock_startdir{
104 0     0     my $self = shift @_;
105              
106 0 0         sysopen(STARTDIR,"$self->{'iraf_start'}/Astro-IRAF-CL.LOCK",O_WRONLY|O_CREAT|O_EXCL) or croak "\nERROR: Could not get a lock on $self->{'iraf_start'}: $!\n\nThis IRAF start directory is already in use by another Astro::IRAF::CL object,\nyou must specify a different starting position via the iraf_start parameter.\n\nDied";
107              
108 0           $self->{'STARTDIR_FH'} = *STARTDIR;
109              
110             }
111              
112             sub _unlock_startdir{
113 0     0     my $self = shift @_;
114              
115 0 0         close ($self->{'STARTDIR_FH'}) or croak "could not close lock FH";
116 0           unlink "$self->{'iraf_start'}/Astro-IRAF-CL.LOCK";
117              
118             }
119              
120             sub _startup{
121 0     0     my $self = shift @_;
122              
123 0           $self->_lock_startdir;
124              
125 0 0         chdir $self->{'iraf_start'} ||croak "Could not cd to $self->{'iraf_start'}";
126              
127 0   0       my $t = Expect->spawn('cl') || croak "Cannot spawn CL: $!";
128              
129 0           $t->expect(30,'-re',$self->{'cl_prompt'});
130 0 0         croak "Did not get CL prompt after starting up" if $t->error;
131              
132 0           $self->{'dead'} = 0; # It is now alive.
133              
134 0           my $output = $t->before();
135 0           my @output = split /\n/,$output;
136 0 0         if ($self->{'display_startup'}){
137 0           for (@output){print STDOUT $_ . "\n"}
  0            
138             }
139              
140 0 0         chdir $self->{'work_dir'} || croak "Could not cd to $self->{'work_dir'}";
141              
142 0           $t->print("cd $self->{'work_dir'}\r");
143 0           $t->expect($TIMEOUT,"cd $self->{'work_dir'}\r\n");
144 0           $t->expect($TIMEOUT,'-re',$self->{'cl_prompt'});
145 0 0         croak "Did not get CL prompt back after trying to cd to $self->{'cl_prompt'}"
146             if $t->error;
147              
148 0           return $t;
149             }
150              
151             sub restart{
152 0     0 0   my $self = shift @_;
153              
154             # Kill the session if it isn't already dead.
155              
156 0 0         $self->end() if !$self->{'dead'};
157              
158             # Reset various parameters so everything works nicely.
159              
160 0           $self->{'dead'} = 0;
161 0           $self->{'cl_prompt'} = qr/^cl>\s+/;
162              
163 0           $self->{'session'} = $self->_startup;
164              
165 0           $self->_get_available_commands_and_packages('main');
166              
167             # Get the list of previously loaded packages then reset the list.
168              
169 0           my @prev_loaded_packages = @{$self->{'packages'}};
  0            
170 0           $self->{'packages'} = [];
171              
172             # Load packages that were originally specified at start time.
173              
174 0 0         if (exists $self->{'start_params'}{'packages'}){
175 0           foreach my $package (@{$self->{'start_params'}{'packages'}}){
  0            
176 0           $self->load_package($package);
177             }
178             }
179              
180             # Set definitions that were originally specified.
181              
182 0 0         if (exists $self->{'start_params'}{'set'}){
183 0           $self->set(%{$self->{'start_params'}{'set'}});
  0            
184             }
185              
186             # Load any other packages that were subsequently loaded.
187              
188 0           foreach my $package (@prev_loaded_packages){
189 0 0         $self->load_package($package) if !$self->package_is_loaded($package);
190             }
191              
192             }
193              
194              
195             sub _internal_command{
196 0     0     my ($self,$command) = @_;
197              
198 0           my $session = $self->{'session'};
199              
200 0           $session->print("$command\r");
201 0           $session->expect($TIMEOUT,"$command\r\n");
202 0           $session->expect($TIMEOUT,'-re',$self->{'cl_prompt'});
203              
204 0           my $output = $session->before();
205 0           $output =~ s/(\r\n)*$//;
206              
207 0           return $output;
208             }
209              
210             ## IRAF package management.
211              
212             sub package_is_loaded{
213 0     0 0   my ($self,$package) = @_;
214              
215 0           my $loaded = grep {$_ eq $package} @{$self->{'packages'}};
  0            
  0            
216              
217 0           return $loaded;
218             }
219              
220             sub package_exists{
221 0     0 0   my ($self,$package) = @_;
222              
223 0           my $defined = $self->_internal_command("print deftask\(\"$package\"\)");
224              
225 0 0         my $result = $defined eq 'yes' ? 1 : 0;
226              
227 0           return $result;
228             }
229              
230              
231             sub load_package{
232 0     0 0   my ($self,$package) = @_;
233              
234 0 0         if (!$self->package_exists($package)){
235 0           croak "Error: Trying to load a package ($package) that does not exist";
236             }
237              
238 0           $self->_register_package($package);
239              
240 0           my $output = $self->_internal_command("$package");
241 0           $self->_add_to_command_history($package);
242              
243 0 0         my @output = $output ? split(/\n/,$output) : ();
244              
245 0           $self->_get_available_commands_and_packages($package);
246              
247 0           return @output;
248             }
249              
250             sub _register_package{
251 0     0     my ($self,$package) = @_;
252              
253 0           my $new_prompt = $self->_get_package_prompt($package);
254              
255 0           $self->_set_cl_prompt($new_prompt);
256              
257 0           unshift @{$self->{'packages'}},$package;
  0            
258              
259             }
260              
261             sub _get_package_prompt{
262 0     0     my ($self,$package) = @_;
263              
264 0           my $new_prompt = substr($package,0,2);
265 0           $new_prompt = qr/^$new_prompt>\s+/;
266              
267 0           return $new_prompt;
268             }
269              
270             sub _deregister_package{
271 0     0     my ($self,$package) = @_;
272              
273 0           my $current_package = $self->get_current_package();
274              
275 0   0       $package ||= $current_package;
276              
277 0 0         croak "Unloading packages in wrong order, current package is $current_package, you are trying to unload $package" if $package ne $current_package;
278              
279 0           shift @{$self->{'packages'}};
  0            
280              
281 0   0       my $next_package = $self->get_current_package() || 'cl';
282              
283 0           my $new_prompt = $self->_get_package_prompt($next_package);
284              
285 0           $self->_set_cl_prompt($new_prompt);
286              
287             }
288              
289             sub unload_package{
290 0     0 0   my ($self,$package) = @_;
291              
292 0           $self->_deregister_package($package);
293              
294 0           my $output = $self->_internal_command('bye');
295 0           $self->_add_to_command_history('bye');
296              
297 0 0         my @output = $output ? split(/\n/,$output) : ();
298              
299 0           delete ${$self->{'available_commands'}}{'package'};
  0            
300 0           delete ${$self->{'available_packages'}}{'package'};
  0            
301              
302 0           return @output;
303             }
304              
305             sub get_current_package{
306 0     0 0   my $self = shift @_;
307              
308 0           my $current_package = ${$self->{'packages'}}[0];
  0            
309              
310 0           return $current_package;
311              
312             }
313              
314             sub unload_all_packages{
315 0     0 0   my $self = shift @_;
316              
317 0           while (defined (my $current_package = $self->get_current_package)){
318 0           $self->unload_package($current_package);
319             }
320              
321             }
322              
323             ##
324              
325             ## History manipulation routines.
326              
327             sub _add_to_command_history{
328 0     0     my ($self,$command) = @_;
329              
330 0           push @{$self->{'command_history'}},$command;
  0            
331              
332 0 0         if ($self->{'debug'}){
333 0           my $log = $self->{'log'};
334 0           print $log 'CL: ' . $command . "\n";
335             }
336              
337             }
338              
339             sub get_from_command_history{
340 0     0 0   my ($self,$position) = @_;
341              
342 0           return ${$self->{'command_history'}}[$position];
  0            
343              
344             }
345              
346             sub exec_from_history{
347 0     0 0   my ($self,$position,%params) = @_;
348              
349 0           my $command = $self->get_from_command_history($position);
350              
351 0           my @output = $self->exec(command => $command,
352             %params);
353              
354 0 0         if (wantarray){
    0          
355 0           return @output;
356             }
357             elsif(defined wantarray){
358 0           return $output[0];
359             }
360              
361             }
362              
363             ## Set parameter routines
364              
365             sub _set_cl_prompt{
366 0     0     my ($self,$prompt) = @_;
367              
368 0           $self->{'cl_prompt'} = $prompt;
369              
370             }
371              
372             sub set_log{
373 0     0 0   my ($self,$log) = @_;
374              
375 0           $self->{'log'} = $log;
376             }
377              
378             ## Error handlers.
379              
380             sub cl_warning_handler{
381 0     0 0   my ($self,$command,$handler) = @_;
382              
383 0           my $session = $self->{'session'};
384 0           $session->expect($TIMEOUT,'-re',$self->{'cl_prompt'});
385              
386 0           my $error = $session->before();
387              
388 0           print STDERR "The command $command encountered a CL Warning:\n\n$error\n";
389              
390 0 0         if (defined $handler){
391 0           print STDERR "Passing off to warning handler\n";
392 0           $handler->($self);
393             }
394              
395 0           return;
396             }
397              
398             sub cl_error_handler{
399 0     0 0   my ($self,$command,$handler) = @_;
400              
401 0           my $session = $self->{'session'};
402 0           $session->expect($TIMEOUT,'-re',$self->{'cl_prompt'});
403              
404 0           my $error = $session->before();
405              
406 0           print STDERR "The command $command encountered a CL ERROR:\n\n$error\n";
407              
408 0 0         if (defined $handler){
409 0           print STDERR "Passing off to error handler\n";
410 0           $handler->($self);
411             }
412             else{
413 0           die;
414             }
415              
416 0           return;
417             }
418              
419             sub eof_handler{
420 0     0 0   my ($self,$command,$handler) = @_;
421              
422 0           print STDERR "The command $command suffered an eof error\n";
423              
424 0 0         if (defined $handler){
425 0           print STDERR "Passing off to death handler\n";
426 0           $handler->($self);
427             }
428             else{
429 0           die;
430             }
431              
432 0           return;
433             }
434              
435             sub timeout_handler{
436 0     0 0   my ($self,$command,$timeout,$handler) = @_;
437              
438 0           my $session = $self->{'session'};
439              
440 0           $session->print("\cc"); # Send the command a control-c to stop it
441 0     0     $session->expect($TIMEOUT,'-re',$self->{'cl_prompt'},
442 0           [eof => sub{&eof_handler($self,"control-c to $command")}]);
443              
444 0           print STDERR "The command \"$command\" timed out after $timeout seconds\n";
445              
446 0 0         if (defined $handler){
447 0           print STDERR "Passing off to timeout handler\n";
448 0           $handler->($self);
449             }
450             else{
451 0           die;
452             }
453              
454 0           return;
455             }
456              
457             ## IRAF session variable management.
458              
459             sub set{
460 0     0 0   my ($self,%params) = @_;
461              
462 0           my @output;
463 0           foreach my $key (keys %params){
464 0           my $value = $params{$key};
465              
466 0           my $output;
467 0 0         if ($self->exists($key)){
468 0           $output = $self->_internal_command("reset $key = $value");
469 0           $self->_add_to_command_history("reset $key = $value");
470             }
471             else{
472 0           $output = $self->_internal_command("set $key = $value");
473 0           $self->_add_to_command_history("set $key = $value");
474             }
475              
476 0           push @output,$output;
477             }
478              
479 0           return @output;
480             }
481              
482             sub show{
483 0     0 0   my ($self,$key) = @_;
484              
485 0           my $output = '';
486 0 0         if ($self->exists($key)){
487 0           $output = $self->_internal_command("show $key");
488 0           $self->_add_to_command_history("show $key");
489             }
490              
491 0           return $output;
492              
493             }
494              
495             sub exists{
496 0     0 0   my ($self,$key) = @_;
497              
498 0           my $output = $self->_internal_command("print (defvar (\"$key\"))");
499              
500 0 0         if ($output eq 'yes'){
501 0           return 1;
502             }
503             else{
504 0           return 0;
505             }
506             }
507              
508             sub _get_available_commands_and_packages{
509 0     0     my ($self,$package) = @_;
510              
511 0           my $list = $self->_internal_command('?');
512              
513 0           my @list = split /\n/,$list;
514              
515 0           my @commands;
516             my @packages;
517 0           foreach my $line (@list){
518 0           chomp $line;
519 0           $line =~ s/^\s+//;
520 0           my @foo = split /\s+/,$line;
521              
522 0           for (@foo){
523 0 0         if (m/^([^.]+)\.$/){
524 0           push @packages,$1;
525             }
526             else{
527 0           push @commands,$_;
528             }
529             }
530              
531             }
532              
533 0           $self->{'available_commands'}{$package} = [@commands];
534 0           $self->{'available_packages'}{$package} = [@packages];
535              
536             }
537              
538             sub list_available_commands{
539 0     0 0   my ($self,$package) = @_;
540              
541 0 0         if (!$package){
542 0           foreach my $package (keys %{$self->{'available_commands'}}){
  0            
543              
544 0           print STDOUT 'Package: ' . $package . "\n";
545              
546 0           foreach my $command (@{$self->{'available_commands'}{$package}}){
  0            
547              
548 0           print STDOUT "\t" . $command . "\n";
549              
550             }
551             }
552             }
553             else{
554              
555 0           print STDOUT 'Package: ' . $package . "\n";
556              
557 0           foreach my $command (@{$self->{'available_commands'}{$package}}){
  0            
558              
559 0           print STDOUT "\t" . $command . "\n";
560              
561             }
562             }
563             }
564              
565             sub list_available_packages{
566 0     0 0   my ($self,$package) = @_;
567              
568 0 0         if (!$package){
569 0           foreach my $package (keys %{$self->{'available_packages'}}){
  0            
570              
571 0           print STDOUT 'Package: ' . $package . "\n";
572              
573 0           foreach my $command (@{$self->{'available_packages'}{$package}}){
  0            
574              
575 0           print STDOUT "\t" . $command . "\n";
576              
577             }
578             }
579             }
580             else{
581              
582 0           print STDOUT 'Package: ' . $package . "\n";
583              
584 0           foreach my $command (@{$self->{'available_packages'}{$package}}){
  0            
585              
586 0           print STDOUT "\t" . $command . "\n";
587              
588             }
589             }
590             }
591              
592             sub package_is_available{
593 0     0 0   my ($self,$package_wanted) = @_;
594              
595 0           foreach my $package_is_loaded (@{$self->{'packages'}},'main'){
  0            
596              
597 0           foreach my $package (@{$self->{'available_packages'}{$package_is_loaded}}){
  0            
598              
599 0 0         return 1 if $package eq $package_wanted;
600             }
601             }
602              
603 0           return 0;
604             }
605              
606             sub command_is_available{
607 0     0 0   my ($self,$command_wanted) = @_;
608              
609 0           foreach my $package_is_loaded (@{$self->{'packages'}},'main'){
  0            
610              
611 0           foreach my $command (@{$self->{'available_commands'}{$package_is_loaded}}){
  0            
612              
613 0 0         return 1 if $command eq $command_wanted;
614             }
615             }
616              
617 0           return 0;
618             }
619              
620             sub exec{
621 0     0 0   my ($self,%params) = @_;
622              
623 0           my $t = $self->{'session'};
624              
625 0           my @commands;
626              
627 0 0         if (exists $params{'command'}){
628 0           @commands = split /\;/,$params{'command'};
629 0           map {s/^\s+//} @commands;
  0            
630             }
631             else{
632 0           croak 'You must specify an IRAF command to execute';
633             }
634              
635 0 0         my $timeout = defined $params{'timeout'} ? $params{'timeout'} : undef;
636 0   0       my $error_handler = $params{'error_handler'} || undef;
637 0   0       my $warning_handler = $params{'warning_handler'} || undef;
638 0   0       my $death_handler = $params{'death_handler'} || undef;
639 0   0       my $timeout_handler = $params{'timeout_handler'} || undef;
640              
641 0           my ($q_timeout,$q_eof,$q_error,$q_warning,$not_available) = (0,0,0,0,0);
642              
643 0           my @output;
644              
645 0           foreach my $command (@commands){
646              
647 0           $self->_add_to_command_history($command);
648              
649 0 0         if (length($command) > 2047){
650 0           my $length = length($command);
651 0           croak "The length of the command $command is $length, this exceeds the maximum allowed CL command buffer size of 2047";
652             }
653              
654 0           my ($helpfile,$helpname) = (0,'');
655 0 0         if ($command =~ m/^help\s+(.+)/){
656 0           $helpname = $1;
657 0           $command = "help $helpname | type dev=text";
658 0           $helpfile = 1;
659             }
660              
661 0 0         if (length($command) > 72){
662              
663 0           my @strings = &_break_into_strings(string => $command,
664             max_length => 72);
665              
666 0           my $command_part;
667 0           for my $k (0..($#strings-1)){
668 0           $command_part = $strings[$k];
669              
670 0           $t->print("$command_part \\\r");
671 0           $t->expect($TIMEOUT,'-ex',"$command_part \\\r\n");
672 0           $t->expect($TIMEOUT,'-re',$self->{'continue_prompt'});
673             }
674 0           $command_part = $strings[$#strings];
675              
676 0           $t->print("$command_part\r");
677 0           $t->expect($TIMEOUT,'-ex',"$command_part\r\n");
678             }
679             else{
680              
681 0           $t->print("$command\r");
682 0     0     $t->expect($TIMEOUT,
683             [timeout => sub {&timeout_handler($self,$command,$TIMEOUT,
684             $timeout_handler);
685 0           $q_timeout = 1}],
  0            
686             '-ex',"$command\r\n");
687             }
688              
689             ## Package management.
690              
691 0           my $possible_prompt = '#THIS SHOULD NEVER BE MATCHED#'; # Unless changed.
692              
693 0 0         if ($command =~ m/^\s*bye\s*$/){ # Removing the current package.
    0          
694 0           $self->_deregister_package();
695             }
696             elsif ($command =~ m/^\s*\w+\s*$/){ # Possibly loading new package.
697 0 0         if ($self->package_is_available($command)){
698 0           $possible_prompt = $self->_get_package_prompt($command);
699             }
700             }
701             ##
702              
703 0     0     $t->expect($timeout,
704             [timeout => sub {&timeout_handler($self,$command,$timeout,
705             $timeout_handler);
706 0     0     $q_timeout = 1; exp_continue}],
  0            
  0            
707             [eof => sub {&eof_handler($self,$command,
708             $death_handler);
709 0     0     $q_eof = 1; exp_continue}],
  0            
  0            
710             '-re','^Warning:',sub {&cl_warning_handler($self,$command,
711             $warning_handler);
712 0           $q_warning = 1; exp_continue},
  0            
713 0     0     '-re','^ERROR:',sub {&cl_error_handler($self,$command,
714             $error_handler);
715 0           $q_error = 1; exp_continue},
  0            
716 0     0     '-ex','No help available for',sub{print STDERR "No help available for $helpname\n";
717 0           $not_available = 1;
718             },
719 0     0     '-re',$possible_prompt,sub{$self->_register_package($command)},
720 0           '-re',$self->{'cl_prompt'});
721              
722 0 0 0       next if ($q_timeout || $q_error || $q_eof || $not_available);
      0        
      0        
723              
724 0           my $output = $t->exp_before();
725 0           my @lines = split /\n/,$output;
726              
727 0           foreach my $line (@lines){
728 0           chomp $line;
729 0           $line =~ s/[\000-\037\x80-\xff]//g; # Remove any crud from the output.
730 0 0 0       push @output,$line if ($helpfile || $line =~ m/(\d|\w)/);
731             }
732              
733             }
734              
735 0 0         if (wantarray){
    0          
736 0           return @output;
737             }
738             elsif(defined wantarray){
739 0           return $output[0];
740             }
741              
742             }
743              
744             sub load_task{
745 0     0 0   my ($self,%params) = @_;
746              
747 0   0       my $name = $params{'name'} || croak 'Need a name for the task';
748 0   0       my $file = $params{'file'} || croak "Need a filename for the task $name";
749 0   0       my $task = $params{'task'} || '';
750 0   0       my $par_file = $params{'par_file'} || 0; # Is there a param file or not?
751              
752 0 0         if ($task){
753 0           open(FH,">$file");
754 0           print FH $task . "\n";
755 0           close(FH);
756             }
757             else{
758 0 0         croak "You must give either a task command or a file containing the command for task $name" if !-e $file;
759             }
760              
761             # Check whether or not the task has been previously defined,
762             # the answer will be 'yes' or 'no'.
763              
764 0           my $defined_task = $self->_internal_command("print deftask\(\"$name\"\)");
765              
766             # If there is not a parameter file to go with this script then we need to
767             # put a $ in front of the task name.
768              
769 0 0         $name = "\$" . $name if !$par_file;
770              
771             # Load the task depending on whether or not it is previously defined.
772              
773 0 0         if ($defined_task eq 'no'){
774 0           $self->_internal_command("task $name = $file");
775 0           $self->_add_to_command_history("task $name = $file");
776             }
777             else{
778 0           $self->_internal_command("redefine $name = $file");
779 0           $self->_add_to_command_history("redefine $name = $file");
780             }
781              
782             }
783              
784             sub _run_command{
785 0     0     my ($self,$command,@pieces) = @_;
786              
787 0           my $class = ref $self;
788 0           $command =~ s/^$class\:\://;
789              
790 0           foreach my $piece (@pieces){
791 0 0         if (ref($piece) eq 'HASH'){
792              
793 0           foreach my $key (keys %{$piece}){
  0            
794 0           my $value = ${$piece}{$key};
  0            
795 0           $command = join ' ',$command,$key;
796 0 0         $command = join '=',$command,$value if defined $value;
797             }
798             }
799             else{
800 0           $command = join ' ',$command,$piece;
801             }
802             }
803              
804 0           my @output = $self->exec(command => $command);
805              
806 0           return @output;
807             }
808              
809             sub end{
810 0     0 0   my $self = shift @_;
811              
812 0 0         return if $self->{'dead'}; # Ensure end() is not called more than once.
813              
814 0           $self->unload_all_packages;
815              
816 0           my $t = $self->{'session'};
817              
818 0           $t->print("\r");
819 0           $t->expect($TIMEOUT,'-re',$self->{'cl_prompt'});
820              
821 0           $t->print("logout\r");
822 0           $t->expect($TIMEOUT,"logout\r\n");
823              
824 0           $t->soft_close();
825              
826 0           $self->_unlock_startdir;
827              
828 0           $self->{'dead'} = 1;
829             }
830              
831             sub DESTROY{
832 0     0     my $self = shift @_;
833              
834 0           $self->end();
835              
836             }
837              
838             sub AUTOLOAD{
839 1     1   5546 no strict 'refs';
  1         2  
  1         657  
840 0     0     my $self = shift @_;
841              
842 0 0 0       if ($AUTOLOAD =~ /.*::get_(\w+)/ && exists $self->{$1}){
843 0           my $attr_name = $1;
844              
845 0     0     *{$AUTOLOAD} = sub { return $_[0]->{$attr_name}};
  0            
  0            
846              
847 0           return $self->{$attr_name};
848             }
849             else{
850 0           my @output = _run_command($self,$AUTOLOAD,@_);
851 0 0         if (wantarray){
    0          
852 0           return @output;
853             }
854             elsif (defined wantarray){
855 0           return $output[0];
856             }
857             }
858              
859             }
860              
861             # Description of subroutine _break_into_strings():
862             #
863             # This is a subroutine to take a long string and break it, on white
864             # space, into sub-strings that are less than or equal to some,
865             # user-specified maximum length.
866             #
867             # It must not break the string in the middle of an assignment context,
868             # e.g. foo = bar, this can only be broken before the foo or after the
869             # bar.
870             #
871             # Anything that is single or double-quoted in an assignment context
872             # must not be broken either. So, foo = "bar baz quux igwop" can only
873             # break before the foo or after the closing double-quote following the
874             # igwop.
875             #
876             # Single-quotes must be allowed inside double-quotes and vice-versa,
877             # escaping of quote signs must also be allowed, e.g. foo = "a'b",
878             # foo = "a\"b", foo = 'a"b', foo = 'a\'b'
879             #
880             # The routine takes in two parameters, the long string to be broken
881             # and the maximum allowed length of the returned strings. Possibly, a
882             # parameter controlling the string separator to split the input string
883             # on could be added. This would also be used for joining the strings
884             # again after tokenisation.
885             #
886             # The routine returns the list of correct length strings upon
887             # completion.
888             #
889             # Currently, single over-length strings are allowed where a long
890             # assignment occurs. A warning is given but possibly an error should
891             # be thrown but for my case the maximum length I will set will be much
892             # lower than the real maximum allowed length.
893             #
894              
895             sub _break_into_strings{
896 0     0     my %params = @_;
897              
898 0   0       my $long_string = $params{'string'} || croak 'Need an input string';
899 0   0       my $max_length = $params{'max_length'} || 75;
900              
901 0           my @tokens = split /\s+/,$long_string;
902 0           my @tokens2;
903              
904             # Variables for storing current state.
905              
906 0           my ($in_assign,$equals,$in_squote,$in_dquote) = (0,0,0,0);
907              
908 0           my $posn = 0;
909 0           for my $token (@tokens){
910              
911 0 0         if ($token eq '=') {
912 0           $in_assign = 1;
913 0           $equals = 1;
914             }
915              
916 0 0         if ($in_assign){
917              
918 0 0         if ($equals){
919              
920             # Append that equals sign along with the necessary whitespace.
921              
922 0           $tokens2[-1] .= ' =';
923              
924             # Look ahead to see what's coming and see if we are going to start
925             # a section of double or single quotes and change state if so.
926              
927 0 0         if ($tokens[$posn+1] =~ m/^\"/){
    0          
928 0           $in_dquote = 1;
929             }
930             elsif ($tokens[$posn+1] =~ m/^\'/){
931 0           $in_squote = 1;
932             }
933             }
934             else{
935              
936             # Append the token plus necessary whitespace.
937              
938 0           $tokens2[-1] = $tokens2[-1] . ' ' . $token;
939              
940             # Work out if we need to close this assignment section yet.
941              
942 0 0 0       if (!$in_squote && !$in_dquote){ # Single value to append so stop.
    0 0        
    0 0        
943 0           $in_assign = 0;
944             }
945             elsif ($in_dquote && $token =~ m/(\\*)\"$/){
946 0           my $num = length $1;
947 0 0 0       if (!$num || (($num % 2) == 0)){ # Even num, thus not escaped.
948 0           $in_dquote = 0;
949 0           $in_assign = 0;
950             }
951             }
952             elsif ($in_squote && $token =~ m/(\\*)\'$/){
953 0           my $num = length $1;
954 0 0 0       if (!$num || (($num % 2) == 0)){ # Even num, thus not escaped.
955 0           $in_squote = 0;
956 0           $in_assign = 0;
957             }
958             }
959              
960             }
961              
962 0           $equals = 0; # Always turn off the equals state.
963             }
964             else{
965 0           push @tokens2,$token; # Nowt special here just add token to output stack.
966             }
967              
968 0           ++$posn; # Keeping track of position in input stack.
969             }
970              
971             # Build final stack of output strings with correct maximum length.
972             # Note that if a single string is longer than the allowed maximum
973             # length it will still be pushed on, thus best to ensure max_length
974             # is a bit less than the real maximum allowed length. I think it's
975             # better this way for my situation than to lose strings or keep
976             # breaking.
977              
978 0           my @output;
979 0           my $i = 0;
980 0           $output[$i] = shift @tokens2;
981              
982 0           while (defined (my $line = shift @tokens2)){
983              
984 0 0         if ((length($output[$i]) + length($line) + 1) <= $max_length){
985 0           $output[$i] = $output[$i] . ' ' . $line;
986             }
987             else{
988 0           ++$i;
989              
990 0           my $length = length($line);
991 0 0         if ($length > $max_length){
992 0           carp "WARNING: Single assignment length ($length) is longer than maximum allowed string length ($max_length) in call to subroutine _break_into_strings(), will use anyway";
993             }
994              
995 0           $output[$i] = $line;
996              
997             }
998             }
999              
1000 0           return @output;
1001             }
1002              
1003              
1004             1;
1005             __END__