File Coverage

blib/lib/Fortran/Format.pm
Criterion Covered Total %
statement 556 577 96.3
branch 242 292 82.8
condition 72 97 74.2
subroutine 85 86 98.8
pod 4 10 40.0
total 959 1062 90.3


line stmt bran cond sub pod time code
1             package Fortran::Format;
2              
3 3     3   51642 use strict;
  3         8  
  3         181  
4 3     3   19 use warnings;
  3         6  
  3         237  
5              
6             our $VERSION = '0.90';
7 3     3   6553 use Data::Dumper;
  3         47876  
  3         341  
8             our $DEBUG = 0;
9 3     3   42 use Carp;
  3         4  
  3         7636  
10              
11             =head1 NAME
12              
13             Fortran::Format - Read and write data according to a standard Fortran 77 FORMAT
14              
15             =head1 SYNOPSYS
16              
17             use Fortran::Format;
18              
19             my $f = Fortran::Format->new("2('N: ',I4,2X)");
20             print $f->write(1 .. 10);
21             # prints the following:
22             # N: 1 N: 2
23             # N: 3 N: 4
24             # N: 5 N: 6
25             # N: 7 N: 8
26             # N: 9 N: 10
27            
28             # if you don't want to save the format object,
29             # just chain the calls:
30             Fortran::Format->new("2('N: ',I4,2X)")->write(1 .. 10);
31              
32             =head1 DESCRIPTION
33              
34             This is a Perl implementation of the Fortran 77 formatted input/output
35             facility. One possible use is for producing input files for old Fortran
36             programs, making sure that their column-oriented records are rigorously
37             correct. Fortran formats may also have some advantages over C in some
38             cases: it is very easy to output an array, reusing the format as needed; and
39             the syntax for repeated columns is more concise. Unlike C, for good or
40             ill, Fortran-formatted fields B exceed their desired width. For
41             example, compare
42              
43             printf "%3d", 12345; # prints "12345"
44             print Fortran::Format->new("I3")->write(12345); # prints "***"
45              
46             This implementation was written in pure Perl, with portability and correctness
47             in mind. It implements the full ANSI standard for Fortran 77 Formats (or at
48             least it should). It was not written with speed in mind, so if you need to
49             process millions of records it may not be what you need.
50              
51             =head1 FORMATS
52              
53             What follows is a very brief summary of Fortran formats. For a rigorous
54             description, see the ANSI standard. A format consists of a list of "edit
55             descriptors" or sublists of edit descriptors. Edit descriptors are separated by
56             commas, but the comma may be omitted if there's no ambiguity. Spaces and case
57             are ignored, except within strings, so 'i 1 2' is the same as 'I12'.
58              
59             =head2 Repeatable edit descriptors
60              
61             The following edit descriptors may be repeated if they are preceded
62             by a number; for example, '3I4' is the same as 'I4,I4,I4' or 'I4I4I4' or
63             'I4,2I4'. Lists can be nested by using parentheses, so '2(I2I3)' is the same
64             as 'I2I3I2I3'. Most descriptors include a width I. If the width is larger
65             than needed, the output is right-justified. If the width is not large enough,
66             the entire field is filled with asterisks.
67              
68             =over
69              
70             =item II
71              
72             =item II.I
73              
74             An integer with width I, and optionally a minimum number of digits
75             I (adding zeroes on the left if needed).
76              
77             =item FI.I
78              
79             An fixed precision floating-point number with width I,
80             and I digits after the decimal point.
81              
82             =item EI.I
83              
84             =item EI.IEI
85              
86             =item DI.I
87              
88             A number in exponential notation with width I,
89             I digits after the decimal point, and optionally I digits after
90             the exponent.
91              
92             =item GI.I
93              
94             =item GI.IEI
95              
96             For values between 0.1 and 10^I, format like I. For values outside that
97             range, format like I.
98              
99             =item FI
100              
101             Treat the variable as Boolean and output either I or I in a field of
102             width I.
103              
104             =item A
105              
106             =item AI
107              
108             Insert a string variable. If the width is not specified, it outputs the
109             entire string. If the width is smaller than the string, the string is
110             truncated (instead of filling with asterisks).
111              
112             =back
113              
114             =head2 Non-repeatable edit descriptors
115              
116             Most of the following descriptors don't output anything but act as control
117             strings. "Non-repeatable" descriptors can be repeated only by including them
118             in a repeated list within parentheses.
119              
120             =over
121              
122             =item 'I'
123              
124             Insert I as is. Quotes may be escaped by doubling them; for example,
125             I<'Joe''s'> produces I.
126              
127             =item IHI...
128              
129             Insert The next I characters after the H as is.
130              
131             =item TI
132              
133             =item TLI
134              
135             =item TRI
136              
137             Move to position I of the current record (T), or I characters to the left
138             (TL), or I characters to the right (TR).
139              
140             =item IX
141              
142             Move I characters to the right.
143              
144             =item /
145              
146             Move to the begining of the next record (the next line).
147              
148             =item :
149              
150             Stop producing output immediately if there are no more variables left to format.
151              
152             =item S
153              
154             =item SP
155              
156             =item SS
157              
158             Control whether the plus sign is included for positive numbers. Include it for
159             SP, do not include it for SS, and use the default (do not include) for S.
160              
161             =item IP
162              
163             Scaling factor for output in exponential notation. By default, a number such
164             as 1.23 would be written as 0.123E+01. When a scaling factor I is given,
165             the decimal point is shifted I positions to the left and the exponent
166             is decreased by I orders of magnitude. With 1P the output would be 1.23E+00.
167              
168             =back
169              
170             =head1 METHODS
171              
172             =over
173              
174             =cut
175              
176             =item new
177              
178             my $format = Fortran::Format->new($format_string);
179              
180             Create a new format object. The string is parsed and compiled when the
181             object is constructed. Croaks if there is a syntax error.
182              
183             =cut
184              
185             # Fortran::Format->new($format_string)
186             # constructs and compiles a new format object
187             sub new {
188 153     153 1 82583 my $class = shift;
189 153   33     729 $class = ref $class || $class;
190 153         732 my $self = bless {
191             format => shift,
192             writer => Fortran::Format::Writer->new,
193             }, $class;
194 153         244 eval {
195 153         387 $self->parse;
196             };
197 153 50       283 if ($@) {
198 0         0 chomp $@;
199 0         0 croak "Fortran::Format parse error: $@; pos=$self->{current_pos}\n",
200             "$self->{format}\n", " " x $self->{current_pos}, "^\ncalled";
201             }
202 153         339 $self;
203             }
204              
205             =item format
206              
207             my $format_string = $format->format;
208              
209             Returns the format string used by the object.
210              
211             =cut
212              
213             # my $format_string = $format->format()
214             # returns the format string
215             sub format {
216 306     306 1 330 my $self = shift;
217 306         647 $self->{format};
218             }
219              
220             sub writer {
221 521     521 0 613 my $self = shift;
222 521         1554 $self->{writer};
223             }
224              
225             # $format->parse()
226             # tokenizes, parses, and compiles the format string
227             sub parse {
228 153     153 0 217 my $self = shift;
229 153         364 my $s = $self->format;
230 153         400 my $toks = $self->tokenize;
231 153 50       339 print "$s\n" if $DEBUG;
232              
233 153         419 my $tree = Fortran::Format::RootList->build($self,
234             repeat => 1, writer => $self->writer);
235 153         270 $self->{tree} = $tree;
236 153 50       402 print Dumper $tree if $DEBUG;
237             }
238              
239             =item write
240              
241             $output = $format->write(@data);
242              
243             Formats the data. This is equivalent to the Fortran C statement,
244             except that it just returns the formatted string. It does not write
245             directly to a file. Data items may be either scalar or array references
246             (which can be nested).
247              
248             For matrices (multidimensional arrays), the contents are formatted in
249             column-major order, same as in Fortran. For example,
250              
251             my $a = [[1,2],[3,4]];
252             Fortran::Format->new('4I4')->write($a);
253              
254             will print
255              
256             1 3 2 4
257              
258             or
259              
260             Fortran::Format->new('2I4')->write($a);
261              
262             will print
263              
264             1 3
265             2 4
266            
267             This is effectively equivalent to transposing the matrix before
268             printing it in the row-major order that would be expected by
269             most non-Fortran programmers. This kludge is necessary
270             to ensure that the output can be read properly by a Fortran
271             program.
272              
273             B: this is incompatible with Fortran::Format 0.5x, which
274             simply flattened the nested arrays, producing the output in row-major
275             order. Also note that the behavior is undefined if the nested array
276             is not rectangular. For example, [[1],[2,3]] will give strange results.
277              
278             =cut
279              
280             # my $output = $format->write(@data)
281             # executes the format and returns the output string
282             sub write {
283 116     116 1 737 my ($self, @data) = @_;
284 116         136 my $output;
285 116         240 my $writer = $self->writer;
286 116         229 $writer->begin;
287 116         275 @data = _flatten(@data);
288 116         314 while (@data) {
289 1021         1134 my $data_count = @data;
290 1021         2556 $self->{tree}->write(\@data);
291 1021         1725 $writer->end_line;
292 1021 50 66     5167 if (@data and @data == $data_count) { # make sure some data was used
293 0         0 croak "infinite format scan for edit descriptor on writing";
294             }
295             }
296 116         244 $writer->output;
297             }
298              
299             # takes a list and "flattens" it by turning array references into list items
300             # example: flatten(1,[2,3],[4,[5,6[7]],8],9) returns (1,2,3,4,5,6,7,8,9)
301             sub _simple_flatten {
302 11     11   23 my (@in) = @_;
303 11         15 my @out;
304 11         19 for my $item (@in) {
305 32 100       61 if (ref $item eq 'ARRAY') {
306 4         17 push @out, _simple_flatten(@$item);
307             } else {
308 28         51 push @out, $item;
309             }
310             }
311 11         41 @out;
312             }
313              
314             sub _flatten {
315 116     116   304 my (@in) = @_;
316 116         131 my @out;
317 116         181 for my $item (@in) {
318 1416 100       1826 if (ref $item eq 'ARRAY') {
319 7         22 push @out, _colum_flatten($item);
320             } else {
321 1409         1722 push @out, $item;
322             }
323             }
324 116         630 @out;
325             }
326              
327             sub _transpose {
328 39     39   64 my ($data, $offs, $size, @dims) = @_;
329 39 100       92 unless (@dims) { return $data->[$offs] }
  28         79  
330 11         24 my $n = pop @dims;
331 11         12 my @ret;
332 11         188 for my $i (0 .. $n-1) {
333 32         90 push @ret, _transpose($data, $offs + $i*$size, $size*$n, @dims);
334             }
335 11         54 @ret;
336             }
337              
338             sub _colum_flatten {
339 7     7   9 my ($in) = @_;
340 7         29 my @temp = _simple_flatten(@$in);
341 7         18 my @dims;
342 7         22 for (my $p = $in; ref $p; $p = $p->[0]) {
343 9         44 push @dims, scalar @$p;
344             }
345 7         106 _transpose(\@temp, 0, 1, @dims);
346             }
347              
348             =item read
349              
350             my (@results) = $format->read($fh, @input_list);
351              
352             Read data from the filehandle $fh using the format ($fh can also be a string
353             instead of a filehandle). The input list is a list of array sizes: 1 for
354             simple scalars, I for simple arrays, and an array reference of dimensions
355             (such as [3,3]) for multidimensional arrays. For example,
356              
357             my ($i, $matrix, $j) = $format->read($fh, 1, [3,3], 2)
358              
359             will read one scalar, followed by a 3x3 matrix, followed by an array with size
360             two. B: this method should be called in list context!
361              
362             The input list is needed because Fortran formats are reused automatically for
363             subsequent lines until all the variables are read.
364              
365             Matrices are read in column-major order. See C for details.
366              
367             When reading, it is also possible to specify the length of the
368             resulting string variables by appending
369             "AI". For example,
370              
371             my $s = $format->read($fh, '1A40')
372              
373             will read the data I a 40-character long string variable (this is
374             regardless of the field width specified in the format string itself). The
375             string will be padded with trailing spaces if needed to ensure that it is
376             exactly 40 characters long. This attempts to emulate Fortran's peculiar string
377             length semantics. It is needed if you want to read a string, write it back,
378             and be sure that you get the exact same output that you would get with
379             Fortran.
380              
381             For example,
382            
383             my $in = 'hello world';
384             my $a5 = Fortran::Format->new('A5');
385             my $a20 = Fortran::Format->new('A20');
386              
387             my ($s) = $a5->read($in, '1A10');
388              
389             print $a20->write($s);
390             # prints " hello "
391              
392             Notice that 1) C<$s> was padded with five space, to a length of ten
393             characters; 2) the output is right-justified to a total width of 20
394             characters.
395              
396             Now, if we do this instead:
397              
398             my ($s) = $a5->read($in, '1A3');
399             print $a20->write($s);
400             # prints " llo"
401              
402             Five character are read from the left of the string ("hello"), but only the
403             rightmost three are copied to the 3-character-long variable ("llo").
404              
405             =cut
406              
407             # possible way of specifying string length:
408             # my ($i, $matrix, $j) = $format->read($fh, 'A40' [3,A40], 1)
409             # my ($i, $matrix, $j) = $format->read($fh, 'A40' '3A40', 1)
410              
411             # READ INTERFACE
412             # --> my ($i, $arr_ref, $j) = $format->read($fh, 1, [3,3], 1)
413             sub read {
414 37     37 1 245 my ($self, $input, @input_list) = @_;
415              
416 37 50       83 unless (wantarray) {
417 0         0 croak "Fortran::Format->read should be called in list context";
418             }
419              
420 37         71 $self->writer->begin(input_list => \@input_list);
421 37         48 my $fh;
422 37 50       67 if (ref $input) {
423 0         0 $fh = $input;
424             } else {
425 2     2   19 open $fh, '<', \$input;
  2         3  
  2         15  
  37         597  
426             }
427 37         3533 while ($self->writer->want_more) {
428 47         99 $self->writer->begin_line;
429 47         145 my $line = <$fh>;
430 47         70 chomp $line;
431 47         112 $self->{writer}{input_line} = $line; # XXX
432 47         147 $self->{tree}->read; # read format once
433 47 50       98 unless ($self->writer->read_something) {
434 0         0 croak "infinite format scan for edit descriptor on reading";
435             }
436             }
437              
438 37         80 $self->writer->input_data;
439             }
440              
441              
442             # $format->tokenize()
443             # separate a string into tokens, which are stored internally by the object
444             # This version works for Hollerith strings
445             sub tokenize {
446 153     153 0 211 my $self = shift;
447 153         283 my $s = $self->format;
448              
449 153         630 my @chars = split '', $s;
450 153         209 my $state = 0;
451 153         164 my @toks;
452 153         184 my ($tok, $len, $char);
453 153         170 my $pos = 0;
454 153         264 my $tok_pos = $self->{current_pos} = 0;
455 153   66     748 while (defined ($char = shift @chars) and ++$pos) {
456 967 100       2186 if ($state == 0) {
    100          
    100          
    100          
    100          
    50          
457 652         703 $tok_pos = $pos - 1;
458 652         979 $tok = uc $char;
459 652 100       1299 $state = 1, next if $char eq "'"; # begin string
460 642 100       5120 $state = 3, next if $char =~ /\d/; # number
461 355 100       797 $state = 5, next if $char =~ /[+-]/; # sign
462 348 100       647 next if $char eq ' '; # skip space
463 339 100       613 next if $char eq ','; # skip comma
464 323         2452 push @toks, {tok => $tok, pos => $tok_pos};
465             } elsif ($state == 1) {
466 53         62 $tok .= $char; # string contents
467 53 100       252 $state = 2, next if $char eq "'"; # quote
468             } elsif ($state == 2) {
469 10 100       29 $state = 1, next if $char eq "'"; # escaped quote
470 9         36 push @toks, {tok => $tok, pos => $tok_pos};
471 9         13 $state = 0, redo; # end of string
472             } elsif ($state == 3) {
473 209 100       460 $len = $tok, $state = 4, $tok = '',
474             next if uc $char eq 'H'; # begin H-string
475 206 100       627 $tok .= $char, next if $char =~ /\d/; # more digits
476 148 100       288 next if $char eq ' '; # skip space
477 142         456 push @toks, {tok => $tok, pos => $tok_pos};
478 142         212 $state = 0, redo; # end of number
479             } elsif ($state == 4) {
480 29 100       57 if ($len-- == 0) {
481 3         11 push @toks, {tok => "'$tok'",
482             pos => $tok_pos}; # end of H-string
483 3         4 $state = 0;
484 3         4 redo;
485             }
486 26         124 $tok .= $char; # string contents
487             } elsif ($state == 5) {
488 14 100       73 $tok .= $char, next if $char =~ /\d/; # more digits
489 7 50       20 next if $char eq ' '; # skip space
490 7         28 push @toks, {tok => $tok, pos => $tok_pos};
491 7         14 $state = 0, redo; # end of number
492             }
493             }
494 153 100 100     806 if ($state == 2 or $state == 3 or $state == 5) {
    50 66        
      33        
495 143         470 push @toks, {tok => $tok, pos => $tok_pos};
496             } elsif ($state == 1 or $state == 4) {
497 0         0 $self->{current_pos} = length $self->format;
498 0         0 die "unfinished string\n";
499             }
500              
501             @toks = map {
502 153 100       302 if ($_->{tok} eq '/') { $_->{tok} = "SLASH" }
  627 100       16488  
  2         3  
503 1         2 elsif ($_->{tok} eq ':') { $_->{tok} = "COLON" }
504             $_
505 627         1088 } @toks;
506              
507 153 50       337 print Dumper \@toks if $DEBUG;
508 153         501 $self->{toks} = \@toks;
509             }
510              
511             sub get_tok {
512 940     940 0 1220 my ($self, $patt) = @_;
513 940         830 my $tok;
514 940 100 100     2654 if (! defined $patt || defined $self->peek_tok($patt)) {
515 780         1059 $tok = shift @{$self->{toks}};
  780         1501  
516 780         1116 my $pos = $tok->{pos};
517 780 100       1577 $self->{current_pos} = $pos if $pos;
518 780         1137 $tok = $tok->{tok};
519 780 50 33     2432 print " <$tok:$pos>\n" if $DEBUG and defined $tok;
520 780         1242 $self->{current_tok} = $tok;
521             }
522 940         3274 $tok;
523             }
524              
525 13     13 0 29 sub current_tok { $_[0]->{current_tok} }
526              
527             sub peek_tok {
528 524     524 0 670 my ($self, $patt) = @_;
529 524         1053 my $tok = $self->{toks}[0]{tok};
530 524 100 100     9277 defined $tok && $tok =~ /$patt/ ? $tok : undef;
531             }
532              
533             package Fortran::Format::InputItem;
534              
535             sub new {
536 37     37   90 my ($class, %opts) = @_;
537 37   33     129 $class = ref $class || $class;
538              
539 37         49 my $dims = $opts{dimensions};
540 37 100       101 $dims = [$dims] unless ref $dims;
541              
542 37         52 my $size = 1;
543 37         36 my @idims;
544 3     3   27 {no warnings; @idims = map { int } @$dims; }
  3         6  
  3         3201  
  37         46  
  37         56  
  39         195  
545 37         115 $size *= $_ for (@idims);
546              
547 37         67 my $last_dim = $dims->[-1];
548 37         46 my $string_length;
549 37 100       83 if ($last_dim =~ /^\d+A(\d+)$/) {
550 3         8 $string_length = $1;
551             }
552              
553 37         186 my $self = bless {
554             dimensions => \@idims,
555             size => $size,
556             data => [],
557             string_length => $string_length,
558             }, $class;
559 37         201 $self;
560             }
561              
562             sub push_data {
563 58     58   77 my ($self, $val) = @_;
564 58 100       128 if ($self->{string_length}) {
565 3 50       8 if (length $val > $self->{string_length}) {
566 0         0 $val = substr $val, length($val) - $self->{string_length};
567             } else {
568 3         9 $val = sprintf "%-$self->{string_length}s", $val;
569             }
570             }
571 58         65 push @{$self->{data}}, $val;
  58         134  
572             }
573              
574             sub contents {
575 58     58   67 my ($self) = @_;
576 58         72 my $data = $self->{data};
577 58 100       152 return undef if @$data < $self->{size};
578             #use Data::Dumper; print "CONTENTS DATA:\n", Dumper $data;
579 37         36 my $ret;
580 37 100       75 if (@$data == 1) { # flatten scalars
581 30         35 $ret = $data->[0];
582             } else {
583 7         9 $ret = _fill_array($data, 0, 1, @{$self->{dimensions}});
  7         26  
584             }
585             #print "CONTENTS RET:\n", Dumper $ret;
586 37         63 $ret;
587             }
588              
589             sub _fill_array {
590 39     39   70 my ($data, $offs, $size, @dims) = @_;
591 39 100       161 unless (@dims) { return $data->[$offs] }
  28         90  
592 11         17 my $n = shift @dims;
593 11         14 my @ret;
594 11         29 for my $i (0 .. $n-1) {
595 32         95 push @ret, _fill_array($data, $offs + $i*$size, $n*$size, @dims);
596             }
597 11         38 \@ret;
598             }
599              
600             package Fortran::Format::Writer;
601              
602             our $DEBUG = 0;
603              
604             sub new {
605 153     153   241 my $class = shift;
606 153   33     536 $class = ref $class || $class;
607 153         905 my $self = bless { }, $class;
608             }
609              
610             sub begin {
611 153     153   263 my ($self, %pars) = @_;
612 153         281 $self->plus('');
613 153         314 $self->bz(0);
614 153         339 $self->scale(0);
615 153         284 $self->reuse(0);
616 153         278 $self->begin_line;
617 153         460 $self->{input_data} = [];
618 153         291 $self->{output} = '';
619 153 100       393 if ($pars{input_list}) {
620 37         187 $self->{input_list} = [ map {
621 37         64 Fortran::Format::InputItem->new(dimensions => $_)
622 37         43 } @{$pars{input_list}} ];
623             # XXX
624             }
625             #use Data::Dumper; print Dumper $self;
626             }
627              
628             sub begin_line {
629 1243     1243   1276 my ($self) = @_;
630 1243         1479 $self->{position} = 0;
631 1243         1565 $self->{current_line} = '';
632 1243         2104 $self->{read_count} = 0;
633             }
634              
635             sub end_line {
636 1043     1043   1096 my ($self) = @_;
637 1043         2141 $self->{output} .= $self->{current_line} . "\n";
638 1043         1670 $self->begin_line;
639             }
640              
641             sub output {
642 116     116   135 my ($self) = @_;
643 116         516 $self->{output};
644             }
645              
646             sub write {
647 1578     1578   3791 my ($self, $s) = @_;
648 1578         2238 my $line = $self->{current_line};
649 1578         1838 my $pos = $self->{position};
650              
651 1578 100       2884 if ($pos > length $line) { # need to pad with spaces
652 61         117 $line .= " " x ($pos - length $line);
653             }
654 1578         2097 substr $line, $pos, length $s, $s;
655 1578         1983 $self->{position} += length $s;
656 1578         5813 $self->{current_line} = $line;
657             }
658              
659             sub read {
660 58     58   84 my ($self, $width) = @_;
661 58         91 my $s = $self->{input_line};
662 3     3   22 no warnings;
  3         5  
  3         1404  
663 58         137 $s = substr($s, $self->{position}, $width);
664 58         185 $s = sprintf "%-*s", $width, $s;
665 58 50       110 print "extracted '$s'\n" if $DEBUG;
666 58         119 $self->position(relative => $width);
667 58         122 $s;
668             }
669              
670             sub put {
671 58     58   79 my ($self, $val) = @_;
672 58         106 my $input = $self->{input_list}[0];
673 58 50       118 print "putting '$val'\n" if $DEBUG;
674 58         83 $self->{read_count}++;
675 58         129 $input->push_data($val);
676 58         199 my $ret = $input->contents;
677 58 100       114 if (defined $ret) {
678 37 50       71 print "full\n" if $DEBUG;
679 37         37 push @{$self->{input_data}}, $ret;
  37         74  
680 37         44 shift @{$self->{input_list}};
  37         68  
681             } else {
682 21 50       82 print "not full yet\n" if $DEBUG;
683             }
684             }
685              
686             sub input_data {
687 37     37   53 my ($self) = @_;
688             #use Data::Dumper; print "HI:\n", Dumper $self->{input_data};
689 37         39 @{$self->{input_data}};
  37         225  
690             }
691              
692             sub want_more {
693 144     144   168 my ($self) = @_;
694 144         134 scalar @{$self->{input_list}};
  144         424  
695             }
696              
697             sub read_something {
698 47     47   59 my ($self) = @_;
699 47         345 $self->{read_count};
700             }
701              
702             sub position {
703 223     223   297 my ($self, $relative, $n) = @_;
704 3 50   3   19 use Carp; confess unless @_ == 3;
  3         4  
  3         3963  
  223         439  
705 223 100       351 if ($relative eq 'relative') {
706 212         286 $self->{position} += $n;
707             } else {
708 11         15 $self->{position} = $n;
709             }
710 223 50       504 $self->{position} = 0 if $self->{position} < 0;
711             }
712              
713             sub plus {
714 1101     1101   1127 my $self = shift;
715 1101 100       1751 if (@_) { $self->{plus} = shift } else { $self->{plus} }
  256         542  
  845         2186  
716             }
717              
718             sub bz {
719 205     205   247 my $self = shift;
720 205 100       328 if (@_) { $self->{bz} = shift } else { $self->{bz} }
  159         298  
  46         170  
721             }
722              
723             sub scale {
724 858     858   917 my $self = shift;
725 858 100       1285 if (@_) { $self->{scale} = shift } else { $self->{scale} }
  283         497  
  575         1182  
726             }
727              
728             sub reuse {
729 2289     2289   2598 my $self = shift;
730 2289 100       3460 if (@_) { $self->{reuse} = shift } else { $self->{reuse} }
  1221         2000  
  1068         4425  
731             }
732              
733             package Fortran::Format::Node;
734              
735             sub build {
736 405     405   482 my $class = shift;
737 405         402 my $tokenizer = shift;
738 405   33     1289 $class = ref $class || $class;
739 405         1748 my $self = bless { repeat => 1, @_ }, $class;
740 405         1038 $self->parse($tokenizer);
741 405         834 $self;
742             }
743              
744             sub new {
745 0     0   0 my $class = shift;
746 0   0     0 $class = ref $class || $class;
747 0         0 my $self = bless { @_ }, $class;
748             }
749              
750             sub writer {
751 6034     6034   6911 my $self = shift;
752 6034         15200 $self->{writer};
753             }
754              
755             sub write {
756 2985     2985   3540 my ($self, $data, $start) = @_;
757 2985         4893 for (1 .. $self->{repeat}) {
758 3175         5366 my $ret = $self->write_once($data, $start);
759 3175 100       6175 return undef unless defined $ret; # ran out of data ?
760 3098 100       7411 if (length $ret) {
761 1578         2816 $self->writer->write($ret);
762             }
763             }
764             }
765              
766             sub read {
767 110     110   133 my ($self, $start) = @_;
768 110         261 for (1 .. $self->{repeat}) {
769 122         297 my $ret = $self->read_once($start);
770 122 100       420 return undef unless defined $ret;
771             }
772 106         456 1;
773             }
774              
775 19     19   27 sub parse {} # do nothing
776              
777             package Fortran::Format::Edit::Quote;
778              
779             our @ISA = "Fortran::Format::Node";
780              
781             sub parse {
782 13     13   16 my ($self, $tokenizer) = @_;
783 13         26 my $s = $tokenizer->current_tok;
784 13         24 chop $s;
785 13         23 substr $s, 0, 1, '';
786 13         38 $self->{quoted_string} = $s;
787             }
788              
789             sub write_once {
790 141     141   155 my ($self, $data) = @_;
791 141         287 return $self->{quoted_string};
792             }
793              
794             package Fortran::Format::Edit::I;
795              
796             our @ISA = "Fortran::Format::Node";
797              
798             sub parse {
799 107     107   163 my ($self, $tokenizer) = @_;
800 107 50       183 my $tok = $tokenizer->get_tok('^\d+$') or die "expected \\d after I\n";
801 107         222 $self->{width} = $tok;
802 107 100       802 if ($tokenizer->get_tok('\.')) {
803 2         6 $tok = $tokenizer->get_tok('^\d+$');
804 2 50       8 defined $tok or die "expected \\d after I\\d.\n";
805 2         7 $self->{min} = $tok;
806             }
807             }
808              
809             sub write_once {
810 848     848   900 my ($self, $data) = @_;
811 848 100       1782 return undef unless @$data;
812 816         1454 my $i = int(shift @$data);
813 816         920 my $s = abs $i;
814 816 100 100     1767 if ($self->{min} and $self->{min} > length $s) { # add leading zeroes?
815 19         31 my $zeroes = $self->{min} - length $s;
816 19         37 $s = "0" x $zeroes . $s;
817             }
818 816 100       1317 if ($i < 0) { # add negative sign?
819 373         609 $s = "-$s";
820             } else {
821 443         919 $s = $self->writer->plus . $s;
822             }
823 816 100 100     2694 if (defined $self->{min} and $self->{min} == 0 and $s == 0) {
      100        
824 1         2 $s = ''; # zero with zero with must be output as blank
825             }
826 816         1817 $s = sprintf "%$self->{width}s", $s; # right-justify
827 816 100       1729 if (length $s > $self->{width}) { # too wide?
828 12         23 $s = "*" x $self->{width};
829             }
830 816         1804 $s;
831             }
832              
833             sub read_once {
834 41     41   52 my ($self) = @_;
835 41 100       143 return undef unless $self->writer->want_more;
836 39         163 my $s = $self->writer->read($self->{width});
837 39 50       180 if ($s =~ /^ *-?[\d ]+$/) {
838 39         119 $s =~ s/^ +//;
839 39 100       90 if ($self->writer->bz) {
840 7         18 $s =~ s/ /0/g;
841             } else {
842 32         86 $s =~ s/ //g;
843             }
844 3     3   23 no warnings;
  3         6  
  3         13578  
845 39         75 my $i = int($s);
846             #print "I parsed '$i'\n";
847 39         77 $self->writer->put($i);
848             } else {
849 0         0 die "invalid integer '$s'\n";
850             }
851 39         133 1;
852             }
853              
854             package Fortran::Format::Edit::F;
855              
856             our @ISA = "Fortran::Format::Node";
857              
858             sub parse {
859 21     21   32 my ($self, $tokenizer) = @_;
860 21 50       51 my $tok = $tokenizer->get_tok('^\d+$') or die "expected \\d after F\n";
861 21         56 $self->{width} = $tok;
862 21 50       41 $tokenizer->get_tok('^\.$') or die "expected . after F\\d\n";
863 21         48 $tok = $tokenizer->get_tok('^\d+$');
864 21 50       56 defined $tok or die "expected \\d after F\\d.\n";
865 21         42 $self->{precision} = $tok;
866             }
867              
868             sub write_once {
869 224     224   278 my ($self, $data) = @_;
870 224 50       456 return undef unless @$data;
871 224         250 my $f = shift @$data;
872 224         403 $f *= 10 ** ($self->writer->scale);
873 224         1156 my $s = sprintf "%.$self->{precision}f", abs $f;
874 224 100 100     705 if ($f < 0.0 and $s =~ /[1-9]/) {
875             # must only include negative sign for non-zero output
876 40         73 $s = "-$s";
877             } else {
878 184         321 $s = $self->writer->plus . $s;
879             }
880 224 100       559 if ($self->{precision} == 0) {
881 50         60 $s .= '.'; # must include decimal point even for Fn.0
882             }
883 224         451 $s = sprintf "%$self->{width}s", $s; # right-justify
884              
885             # Remove optional zero if width is too big by one
886 224 100       592 $s =~ s/^([+-]?)0.(\d)/$1.$2/ if length $s == $self->{width} + 1;
887 224 100       412 if (length $s > $self->{width}) { # too wide?
888 81         120 $s = "*" x $self->{width};
889             }
890              
891 224         487 $s;
892             }
893              
894             sub read_once {
895 8     8   12 my ($self) = @_;
896 8 50       16 return undef unless $self->writer->want_more;
897 8         14 my $s = $self->writer->read($self->{width});
898 8         9 my $f;
899              
900 8 100 66     63 if ($s =~ /^ *-?(?:[\d ]*\.?[\d ]*)$/ and $s =~ /\d/) {
    50          
901 7         21 $s =~ s/^ +//; # remove leading spaces
902 7 50       16 if ($self->writer->bz) {
903 0         0 $s =~ s/ /0/g;
904             } else {
905 7         15 $s =~ s/ //g;
906             }
907 7 100       19 unless ($s =~ /\./) {
908 3         9 substr $s, length($s) - $self->{precision}, 0, '.';
909             }
910             #no warnings;
911 7         15 $f = $s / 10**($self->writer->scale);
912             #print "F parsed '$i'\n";
913             #$self->writer->put($i);
914             } elsif ($s =~ /^[ .]*$/) {
915 1         2 $f = 0;
916             } else {
917 0         0 die "invalid F number'$s'\n";
918             }
919 8         16 $self->writer->put($f);
920 8         28 1;
921             }
922              
923             package Fortran::Format::Edit::D;
924              
925             our @ISA = "Fortran::Format::Node";
926              
927             sub parse {
928 28     28   49 my ($self, $tokenizer) = @_;
929 28 50       62 $self->{width} = $tokenizer->get_tok('^\d+$')
930             or die "expected \\d after [DE]\n";
931 28 50       69 $tokenizer->get_tok('\.') or die "expected . after [DE]\\d\n";
932 28         72 my $tok = $tokenizer->get_tok('^\d+$');
933 28 50       74 defined $tok or die "expected \\d after [DE]\\d.\n";
934 28         66 $self->{precision} = $tok;
935             }
936              
937             sub write_once {
938 312     312   368 my ($self, $data) = @_;
939 312 50       602 return undef unless @$data;
940 312         251 my $s; # working string
941              
942 312         360 my $d = shift @$data;
943              
944             # shorthand
945 312         564 my $scale = $self->writer->scale;
946 312         499 my $width = $self->{width};
947 312         409 my $precision = $self->{precision};
948 312   100     874 my $exp_width = $self->{exp_width} || 0;
949              
950             # get exponent
951 312         1473 my $spf = sprintf "%.3E", $d;
952 312         1201 my ($exp) = $spf =~ /E(.*)/g; # maybe floor log10 abs is faster?
953              
954             # normalize to "apparent" magnitude
955 312         947 my $dnorm = abs $d * 10**($scale - $exp - 1);
956              
957             # validate scale factor range (from standard, 13.5.9.2.2)
958 312 100 100     1609 if ($scale <= 0 and -$precision < $scale
      66        
      66        
959             or $scale > 0 and ($precision + 2) > $scale) {
960              
961             # apply scale factor
962 296 100       716 $exp += -$scale + 1 if ($d != 0.0);
963 296 100       532 $precision += -$scale + 1 if ($scale > 0);
964              
965 296 100       510 if ( !$exp_width ) { # calculate default exp. width
966 192 100       333 $exp_width = (abs $exp > 99) ? 3 : 2;
967             }
968              
969             # format exponent
970 296         655 my $exp_s = sprintf "%+0*d", $exp_width + 1, $exp;
971 296 100 100     1045 if ($self->{exp_width} or $exp_width != 3) { # add optional E
972 272         466 $exp_s = $self->exp_char . "$exp_s";
973             }
974              
975             # proceed if exponent didn't overflow
976 296 100       659 if (length $exp_s <= $exp_width + 2) {
977             # format string (at last!)
978 288         1144 $s = sprintf "%.${precision}f$exp_s", $dnorm;
979              
980             # add sign if needed
981 288 100 66     915 if ($d < 0.0 and $s =~ /[1-9]/) {
982             # must only include negative sign for non-zero output
983 70         118 $s = "-$s";
984             } else {
985 218         396 $s = $self->writer->plus . $s;
986             }
987              
988             # must include decimal point even for Fn.0
989 288 50       804 $s =~ s/(\d)(E?[+-])/$1.$2/ unless ($s =~ /\./);
990              
991             # right-justify
992 288         629 $s = sprintf "%${width}s", $s;
993              
994             # Remove optional zero if width is too big by one
995 288 100       863 $s =~ s/^([+-]?)0.(\d)/$1.$2/ if length $s == $width + 1;
996              
997             # make sure final result did not overflow
998 288 100       678 $s = undef if length $s > $width;
999             }
1000             }
1001 312 100       1082 $s || "*" x $width;
1002             }
1003              
1004 28     28   46 sub exp_char { "D" }
1005              
1006              
1007             package Fortran::Format::Edit::E;
1008              
1009             our @ISA = "Fortran::Format::Edit::D";
1010              
1011             sub parse {
1012 26     26   51 my ($self, $tokenizer) = @_;
1013 26         97 $self->SUPER::parse($tokenizer); # mostly similar to D
1014 26 100       65 if ($tokenizer->get_tok('^E$')) {
1015 7 50       20 $self->{exp_width} = $tokenizer->get_tok('^\d+$')
1016             or die "expected \\d after E\\d.\\dE\n";
1017             }
1018             }
1019              
1020 244     244   450 sub exp_char { "E" }
1021              
1022              
1023             package Fortran::Format::Edit::G;
1024              
1025             our @ISA = "Fortran::Format::Edit::E";
1026              
1027             sub write_once {
1028 32     32   34 my ($self, $data) = @_;
1029 32 50       85 return undef unless @$data;
1030 32         24 my $s; # working string
1031              
1032 32         35 my $d = $data->[0]; # just peek to decide who'll handle the formatting
1033              
1034             # shorthand
1035 32         53 my $scale = $self->writer->scale;
1036 32         52 my $width = $self->{width};
1037 32         36 my $precision = $self->{precision};
1038 32   100     78 my $exp_width = $self->{exp_width} || 0;
1039              
1040             # get exponent
1041 32         150 my $spf = sprintf "%.3E", $d;
1042 32         106 my ($exp) = $spf =~ /E(.*)/g; # maybe floor log10 abs is faster?
1043            
1044 32 100 100     124 if ($exp < -1 or $exp >= $precision) {
1045             # format as E
1046 16         38 $s = $self->SUPER::write_once($data);
1047             } else {
1048 16 100       24 my $right_margin = $exp_width ? $exp_width + 2 : 4;
1049              
1050 16         21 $self->{width} -= $right_margin;
1051 16         21 $self->{precision} = $precision - $exp - 1;
1052 16         54 $s = $self->Fortran::Format::Edit::F::write_once($data);
1053 16         31 $s .= " " x $right_margin;
1054 16         23 $self->{precision} = $precision;
1055 16         21 $self->{width} = $width;
1056             }
1057 32 50       87 $s || "*" x $width;
1058             }
1059              
1060             package Fortran::Format::Edit::L;
1061              
1062             our @ISA = "Fortran::Format::Node";
1063              
1064             sub parse {
1065 25     25   33 my ($self, $tokenizer) = @_;
1066 25 50       40 $self->{width} = $tokenizer->get_tok('^\d+$')
1067             or die "expected \\d after F\n";
1068             }
1069              
1070             sub write_once {
1071 33     33   39 my ($self, $data) = @_;
1072 33 100       57 return undef unless @$data;
1073 32         40 my $l = shift @$data;
1074 32 100       126 sprintf "%$self->{width}s", $l ? 'T' : 'F';
1075             }
1076              
1077             sub read_once {
1078 8     8   9 my ($self) = @_;
1079 8 50       23 return undef unless $self->writer->want_more;
1080 8         15 my $s = $self->writer->read($self->{width});
1081 8         10 my $b;
1082              
1083 8 100       35 if ($s =~ /^ *\.?[tT]/) {
    50          
1084 6         7 $b = 1;
1085             } elsif ($s =~ /^ *\.?[fF]/) {
1086 2         4 $b = 0;
1087             } else {
1088 0         0 die "invalid F format '$s'\n";
1089             }
1090 8         14 $self->writer->put($b);
1091 8         24 1;
1092             }
1093              
1094             package Fortran::Format::Edit::X;
1095              
1096             our @ISA = "Fortran::Format::Node";
1097              
1098             sub write_once {
1099 132     132   137 my ($self, $data) = @_;
1100 132         195 $self->writer->position( relative => 1 );
1101 132         207 "";
1102             }
1103              
1104             package Fortran::Format::Edit::SLASH;
1105              
1106             our @ISA = "Fortran::Format::Node";
1107              
1108             sub write_once {
1109 22     22   25 my ($self, $data) = @_;
1110 22         33 $self->writer->end_line;
1111 22         32 "";
1112             }
1113              
1114             package Fortran::Format::Edit::COLON;
1115              
1116             our @ISA = "Fortran::Format::Node";
1117              
1118             sub write_once {
1119 11     11   13 my ($self, $data) = @_;
1120 11 100       23 return undef unless @$data;
1121 10         16 "";
1122             }
1123              
1124              
1125             package Fortran::Format::Edit::A;
1126              
1127             our @ISA = "Fortran::Format::Node";
1128              
1129             sub parse {
1130 11     11   14 my ($self, $tokenizer) = @_;
1131 11         25 $self->{width} = $tokenizer->get_tok('^\d+$');
1132             }
1133              
1134             sub write_once {
1135 55     55   65 my ($self, $data) = @_;
1136 55 100       105 return undef unless @$data;
1137 53         73 my $datum = shift @$data;
1138 53         90 my $s;
1139 53 100       98 if (defined $self->{width}) {
1140 33 100       64 if (length $datum > $self->{width}) { # truncate
1141 10         18 $s = substr $datum, 0, $self->{width};
1142             } else { # justify
1143 23         69 $s = sprintf "%$self->{width}s", $datum;
1144             }
1145             } else { # use as is
1146 20         27 $s = $datum;
1147             }
1148 53         108 $s;
1149             }
1150              
1151             sub read_once {
1152 3     3   4 my ($self) = @_;
1153 3 50       9 return undef unless $self->writer->want_more;
1154 3         7 my $s = $self->writer->read($self->{width});
1155 3         6 $self->writer->put($s);
1156 3         10 1;
1157             }
1158              
1159              
1160             package Fortran::Format::Edit::S;
1161              
1162             our @ISA = "Fortran::Format::Node";
1163              
1164             sub parse {
1165 8     8   17 my ($self, $tokenizer) = @_;
1166 8         26 $self->{plus} = ''; # default is no plus
1167 8 100       16 if (my $tok = $tokenizer->get_tok('^[SP]$')) {
1168 7 100       30 $self->{plus} = '+' if $tok eq 'P';
1169             }
1170             }
1171              
1172             sub write_once {
1173 103     103   110 my ($self) = @_;
1174 103         164 $self->writer->plus($self->{plus});
1175 103         179 '';
1176             }
1177              
1178             package Fortran::Format::Edit::B;
1179              
1180             our @ISA = "Fortran::Format::Node";
1181              
1182             sub parse {
1183 6     6   9 my ($self, $tokenizer) = @_;
1184 6 50       13 my $tok = $tokenizer->get_tok('^[NZ]$')
1185             or die "expected [NZ] after B\n";
1186 6 100       34 $self->{bz} = $tok eq 'Z' ? 1 : 0;
1187             }
1188              
1189             sub read_once {
1190 6     6   12 my ($self) = @_;
1191 6         17 $self->writer->bz($self->{bz});
1192 6         8 1;
1193             }
1194              
1195             package Fortran::Format::Edit::P;
1196              
1197             our @ISA = "Fortran::Format::Node";
1198              
1199             sub write_once {
1200 130     130   130 my ($self) = @_;
1201 130         209 $self->writer->scale($self->{scale});
1202 130         218 '';
1203             }
1204              
1205             sub read_once {
1206 2     2   8 write_once(@_);
1207             }
1208              
1209             package Fortran::Format::Edit::T;
1210              
1211             our @ISA = "Fortran::Format::Node";
1212              
1213             sub parse {
1214 3     3   4 my ($self, $tokenizer) = @_;
1215 3 100       6 if ($tokenizer->get_tok('^R$')) {
    100          
    50          
1216 1 50       6 my $tok = $tokenizer->get_tok('^\d+$')
1217             or die "expected \\d after TR\n";
1218 1         3 $self->{delta} = $tok;
1219             } elsif ($tokenizer->get_tok('^L$')) {
1220 1 50       4 my $tok = $tokenizer->get_tok('^\d+$')
1221             or die "expected \\d after TL\n";
1222 1         8 $self->{delta} = -$tok;
1223             } elsif (my $tok = $tokenizer->get_tok('^\d+$')) {
1224 1         8 $self->{position} = $tok;
1225             } else {
1226 0         0 die "expected \\d after T\n";
1227             }
1228             }
1229              
1230             sub write_once {
1231 33     33   55 my ($self) = @_;
1232 33 100       83 if ($self->{position}) { # absolute position (T)
    50          
1233 11         18 $self->writer->position( absolute => $self->{position} - 1 ); # Fortran is 1-based
1234             } elsif ($self->{delta}) { # relative position (TR, TL)
1235 22         31 $self->writer->position( relative => $self->{delta} );
1236             }
1237 33         55 '';
1238             }
1239              
1240              
1241             package Fortran::Format::List;
1242              
1243             our @ISA = "Fortran::Format::Node";
1244              
1245             sub nodes {
1246 1187     1187   1243 my ($self) = @_;
1247 1187         1076 @{$self->{nodes}}
  1187         2770  
1248             }
1249              
1250             sub parse {
1251 164     164   432 my ($self, $tokenizer) = @_;
1252 164         367 $self->{nodes} = my $nodes = [];
1253 164         205 my $repeat = 1;
1254              
1255 164         377 while (defined (my $tok = $tokenizer->get_tok)) {
1256 293 100       2007 if ($tok =~ /^[+-]?\d+$/) {
    100          
    100          
    100          
    100          
    50          
1257             # should check that next token is repeatable and $tok > 0
1258 40 100       90 if ($tokenizer->get_tok('P')) { # scale factor
    50          
1259 10         30 push @$nodes, Fortran::Format::Edit::P->build($tokenizer,
1260             writer => $self->writer, scale => $tok );
1261             } elsif ($tokenizer->peek_tok('^[IFEDGLAX(]$')) {
1262 30 50 33     184 if ($tok =~ /^[+-]/ or $tok == 0) {
1263 0         0 die "repeat count should be unsigned and non-zero\n";
1264             } else {
1265 30         138 $repeat = $tok;
1266             }
1267             } else {
1268 0         0 die "number not followed by repeatable token\n";
1269             }
1270             } elsif ($tok eq '(') {
1271 11         31 push @$nodes, $self->{last_list} = Fortran::Format::List->build(
1272             $tokenizer,
1273             repeat => $repeat,
1274             writer => $self->writer
1275             );
1276 11         31 $repeat = 1;
1277             } elsif ($tok eq ')') {
1278 11         19 return; # end of list
1279             } elsif ($tok =~ /^'/) {
1280 13         59 push @$nodes, Fortran::Format::Edit::Quote->build($tokenizer,
1281             writer => $self->writer);
1282             } elsif ($tok =~ /^[IFEDGLAX]$/i) { # repeatable tokens
1283             # NOTE: X is technically not a repeatable token; the
1284             # "repeat" count is suposedly mandatory, but at least g77, ifc,
1285             # and pgf77 don't really care (and neither do most programmers)
1286 198         596 push @$nodes, "Fortran::Format::Edit::$tok"->build(
1287             $tokenizer,
1288             writer => $self->writer,
1289             repeat => $repeat,
1290             );
1291 198         587 $repeat = 1;
1292             } elsif ($tok =~ /^([STB]|SLASH|COLON)$/) { # non-repeatable tokens
1293 20         70 push @$nodes, "Fortran::Format::Edit::$tok"->build(
1294             $tokenizer,
1295             writer => $self->writer
1296             );
1297             } else {
1298 0         0 die "invalid or unimplemented token: $tok\n";
1299             }
1300             }
1301             }
1302              
1303             sub write_once {
1304 1133     1133   1384 my ($self, $data, $start) = @_;
1305              
1306 1133         1114 my $started;
1307 1133         1934 for my $node ($self->nodes) {
1308 1975 100 100     4226 next if $start and !$started and $node != $start;
      100        
1309 1964         2008 $started = 1;
1310              
1311 1964         3414 my $ret = $node->write($data);
1312 1964 100       3801 return undef unless defined $ret; # ran out of data ?
1313 1923 50       4327 if (length $ret) {
1314 0         0 $self->{writer}->write($ret);
1315             }
1316             }
1317 1092         2204 ''; # this function does not produce new text
1318             }
1319              
1320             sub read_once {
1321 54     54   68 my ($self, $start) = @_;
1322              
1323 54         60 my $started;
1324 54         124 for my $node ($self->nodes) {
1325 67 100 66     190 next if $start and !$started and $node != $start;
      100        
1326 63         66 $started = 1;
1327              
1328 63         326 my $ret = $node->read;
1329 63 100       203 return undef unless defined $ret;
1330             }
1331 52         88 1;
1332             }
1333              
1334             package Fortran::Format::RootList;
1335              
1336             our @ISA = "Fortran::Format::List";
1337              
1338             sub write {
1339 1021     1021   1358 my ($self, $data) = @_;
1340 1021 100 100     1545 if ($self->writer->reuse() and $self->{last_list}) {
1341 43         129 $self->SUPER::write($data, $self->{last_list});
1342             } else {
1343 978         2189 $self->SUPER::write($data);
1344             }
1345 1021         2033 $self->writer->reuse(1);
1346 1021         1229 ''; # this function does not produce new text
1347             }
1348              
1349             sub read {
1350 47     47   62 my ($self) = @_;
1351 47 100 100     86 if ($self->writer->reuse() and $self->{last_list}) {
1352 3         10 $self->SUPER::read($self->{last_list});
1353             } else {
1354 44         120 $self->SUPER::read;
1355             }
1356 47         269 $self->writer->reuse(1);
1357 47         98 ''; # this function does not produce new text
1358             }
1359              
1360              
1361              
1362              
1363              
1364             1;
1365              
1366              
1367             =back
1368              
1369             =head1 VERSION
1370              
1371             0.90
1372              
1373             =head1 SEE ALSO
1374              
1375             The Fortran format specification:
1376             L
1377              
1378             =head1 AUTHOR
1379              
1380             Ivan Tubert-Brohman Eitub@cpan.orgE
1381              
1382             =head1 COPYRIGHT
1383              
1384             Copyright (c) 2005 Ivan Tubert-Brohman. All rights reserved. This program is
1385             free software; you can redistribute it and/or modify it under the same terms
1386             as Perl itself.
1387              
1388             =cut
1389