]> git.donarmstrong.com Git - perltidy.git/commitdiff
updates preparing for next release 20200907
authorSteve Hancock <perltidy@users.sourceforge.net>
Sun, 6 Sep 2020 19:43:34 +0000 (12:43 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Sun, 6 Sep 2020 19:43:34 +0000 (12:43 -0700)
26 files changed:
CHANGES.md
MANIFEST
bin/perltidy
docs/ChangeLog.html
docs/Tidy.html
docs/perltidy.html
lib/Perl/Tidy.pm
lib/Perl/Tidy.pod
lib/Perl/Tidy/Debugger.pm
lib/Perl/Tidy/DevNull.pm
lib/Perl/Tidy/Diagnostics.pm
lib/Perl/Tidy/FileWriter.pm
lib/Perl/Tidy/Formatter.pm
lib/Perl/Tidy/HtmlWriter.pm
lib/Perl/Tidy/IOScalar.pm
lib/Perl/Tidy/IOScalarArray.pm
lib/Perl/Tidy/IndentationItem.pm
lib/Perl/Tidy/LineBuffer.pm
lib/Perl/Tidy/LineSink.pm
lib/Perl/Tidy/LineSource.pm
lib/Perl/Tidy/Logger.pm
lib/Perl/Tidy/Tokenizer.pm
lib/Perl/Tidy/VerticalAligner.pm
lib/Perl/Tidy/VerticalAligner/Alignment.pm
lib/Perl/Tidy/VerticalAligner/Line.pm
t/snippets/perltidy_random_parameters.pl

index a438761c4e7c3c5c3384d120dae62f3eb62dcb96..03a9210fc31bdab3b5d73c07aad8c93dd935dcbc 100644 (file)
@@ -1,5 +1,19 @@
 # Perltidy Change Log
 
+## 2020 09 07
+
+    - Fixed a bug when the combination -scbb -csc was used.  It occurs in perltidy
+      versions 20200110, 20200619, and 20200822.  What happens is
+      that when two consecutive lines with isolated closing braces had new side
+      comments generated by the -csc parameter, a separating newline was missing.
+      The resulting script will not then run, but worse, if it is reformatted with
+      the same parameters then closing side comments could be overwritten and data
+      lost. 
+
+      This problem was found during automated random testing.  The parameter
+      -scbb is rarely used, which is probably why this has not been reported.  Please
+      upgrade your version.
+
     - Added parameter --non-indenting-braces, or -nib, which prevents
       code from indenting one level if it follows an opening brace marked 
       with a special side comment, '#<<<'.  For example,
index 380314dba53d16dd26f24b9d1dd8bde8805cd325..0a3137ddf6e9eecdab67b357f4a21ec97387750a 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -18,6 +18,7 @@ examples/ex_mp.pl
 examples/filter_example.in
 examples/filter_example.pl
 examples/find_naughty.pl
+examples/fix-scbb-csc-bug.pl
 examples/lextest
 examples/perlcomment.pl
 examples/perllinetype.pl
index 2685c505a80e13cf6148063c6940a3163f21d41d..c499b9487bf084af09eae98a8eac8c26fa79c9fe 100755 (executable)
@@ -851,9 +851,10 @@ The default is not to do this, indicated by B<-nicb>.
 =item B<-nib>, B<--non-indenting-braces>
 
 Normally, lines of code contained within a pair of block braces receive one
-additional level of indentation.  If this flag is set, perltidy will look for
-opening block braces which are followed by a special side comment, which is
-B<#<<<> by default.  If found, the code between this opening brace and its
+additional level of indentation.  This flag, which is enabled by default, 
+causes perltidy to look for
+opening block braces which are followed by a special side comment. This special
+side comment is B<#<<<> by default.  If found, the code between this opening brace and its
 corresponding closing brace will not be given the normal extra indentation
 level.  For example:
 
@@ -864,23 +865,24 @@ level.  For example:
 
             }
 
-            # this line cannot 'see' $var;
+            # this line does not 'see' $var;
 
 This can be useful, for example, when combining code from different files.
 Different sections of code can be placed within braces to keep their lexical
-variables from being visible to the end of the file.  To keep the new blocks
-from causing all of their contained code to be reformatted if you run perltidy, 
-you can mark the opening braces with this special side comment.
+variables from being visible to the end of the file.  To keep the new braces
+from causing all of their contained code to be indented if you run perltidy,
+and possibly introducing new line breaks in long lines, you can mark the
+opening braces with this special side comment.
 
 Only the opening brace needs to be marked, since perltidy knows where the
 closing brace is.  Braces contained within marked braces may also be marked
 as non-indenting.
 
-This feature is on by default.  If your code happens to have some opening
-braces followed by '#<<<', and you don't want this, you can use B<-nnib> to
-deactivate it.  To make it easy to remember, the default string is the same as
-the string for starting a B<format-skipping> section. There is no confusion
-because in that case it is for a block comment rather than a side-comment. 
+If your code happens to have some opening braces followed by '#<<<', and you
+don't want this behavior, you can use B<-nnib> to deactivate it.  To make it
+easy to remember, the default string is the same as the string for starting a
+B<format-skipping> section. There is no confusion because in that case it is
+for a block comment rather than a side-comment. 
 
 The special side comment can be changed with the next parameter.
 
@@ -4110,7 +4112,7 @@ The perltidy binary uses the Perl::Tidy module and is installed when that module
 
 =head1 VERSION
 
-This man page documents perltidy version 20200822
+This man page documents perltidy version 20200907
 
 =head1 BUG REPORTS
 
index 609978cc48fd14105a634ea5b1d4e9e33310908c..c36bf85c0b8306469beda9ab22e2ab1e7e57ad66 100644 (file)
@@ -1,5 +1,40 @@
 <h1>Perltidy Change Log</h1>
 
+<h2>2020 09 07</h2>
+
+<pre><code>- Fixed a bug when the combination -scbb -csc was used.  It occurs in perltidy
+  versions 20200110, 20200619, and 20200822.  What happens is
+  that when two consecutive lines with isolated closing braces had new side
+  comments generated by the -csc parameter, a separating newline was missing.
+  The resulting script will not then run, but worse, if it is reformatted with
+  the same parameters then closing side comments could be overwritten and data
+  lost. 
+
+  This problem was found during automated random testing.  The parameter
+  -scbb is rarely used, which is probably why this has not been reported.  Please
+  upgrade your version.
+
+- Added parameter --non-indenting-braces, or -nib, which prevents
+  code from indenting one level if it follows an opening brace marked 
+  with a special side comment, '#&lt;&lt;&lt;'.  For example,
+
+                { #&lt;&lt;&lt;   a closure to contain lexical vars
+
+                my $var;  # this line does not indent
+
+                }
+
+                # this line cannot 'see' $var;
+
+  This is on by default.  If your code happens to have some
+  opening braces followed by '#&lt;&lt;&lt;', and you
+  don't want this, you can use -nnib to deactivate it. 
+
+- Side comment locations reset at a line ending in a level 0 open
+  block, such as when a new multi-line sub begins.  This is intended to 
+  help keep side comments from drifting to far to the right.
+</code></pre>
+
 <h2>2020 08 22</h2>
 
 <pre><code>- Fix RT #133166, encoding not set for -st.  Also reported as RT #133171
index b6cf9995c4ddcc02577c2f9b3c7dcdcab2bfd0e9..398fcea449d4383ba37b4cc3c3d346761503d209 100644 (file)
 
 <h1 id="VERSION">VERSION</h1>
 
-<p>This man page documents Perl::Tidy version 20200822</p>
+<p>This man page documents Perl::Tidy version 20200907</p>
 
 <h1 id="LICENSE">LICENSE</h1>
 
index 4e33e25f741b7de8dc3b6784b997989f15734f24..d405027651a3b87f4de1032c5f696951ba21abd4 100644 (file)
 
 <p>The default is not to do this, indicated by <b>-nicb</b>.</p>
 
+</dd>
+<dt id="nib---non-indenting-braces"><b>-nib</b>, <b>--non-indenting-braces</b></dt>
+<dd>
+
+<p>Normally, lines of code contained within a pair of block braces receive one additional level of indentation. This flag, which is enabled by default, causes perltidy to look for opening block braces which are followed by a special side comment. This special side comment is <b>#&lt;&lt;&lt;</b> by default. If found, the code between this opening brace and its corresponding closing brace will not be given the normal extra indentation level. For example:</p>
+
+<pre><code>            { #&lt;&lt;&lt;   a closure to contain lexical vars
+
+            my $var;  # this line does not get one level of indentation
+            ...
+
+            }
+
+            # this line does not &#39;see&#39; $var;</code></pre>
+
+<p>This can be useful, for example, when combining code from different files. Different sections of code can be placed within braces to keep their lexical variables from being visible to the end of the file. To keep the new braces from causing all of their contained code to be indented if you run perltidy, and possibly introducing new line breaks in long lines, you can mark the opening braces with this special side comment.</p>
+
+<p>Only the opening brace needs to be marked, since perltidy knows where the closing brace is. Braces contained within marked braces may also be marked as non-indenting.</p>
+
+<p>If your code happens to have some opening braces followed by &#39;#&lt;&lt;&lt;&#39;, and you don&#39;t want this behavior, you can use <b>-nnib</b> to deactivate it. To make it easy to remember, the default string is the same as the string for starting a <b>format-skipping</b> section. There is no confusion because in that case it is for a block comment rather than a side-comment.</p>
+
+<p>The special side comment can be changed with the next parameter.</p>
+
+</dd>
+<dt id="nibp-s---non-indenting-brace-prefix-s"><b>-nibp=s</b>, <b>--non-indenting-brace-prefix=s</b></dt>
+<dd>
+
+<p>The <b>-nibp=string</b> parameter may be used to change the marker for non-indenting braces. The default is equivalent to -nibp=&#39;#&lt;&lt;&lt;&#39;. The string that you enter must begin with a # and should be in quotes as necessary to get past the command shell of your system. This string is the leading text of a regex pattern that is constructed by appending pre-pending a &#39;^&#39; and appending a&#39;\s&#39;, so you must also include backslashes for characters to be taken literally rather than as patterns.</p>
+
+<p>For example, to match the side comment &#39;#++&#39;, the parameter would be</p>
+
+<pre><code>  -nibp=&#39;#\+\+&#39;</code></pre>
+
 </dd>
 <dt id="olq---outdent-long-quotes"><b>-olq</b>, <b>--outdent-long-quotes</b></dt>
 <dd>
                 1, 4, 6, 4, 1,);
  #&gt;&gt;&gt;</code></pre>
 
+<p>Format skipping begins when a format skipping comment is seen and continues until either a format-skipping end pattern is found or until the end of file.</p>
+
 <p>The comment markers may be placed at any location that a block comment may appear. If they do not appear to be working, use the -log flag and examine the <i>.LOG</i> file. Use <b>-nfs</b> to disable this feature.</p>
 
 <p>This method works for any code. For the specific case of a comma-separated list of values, as in this example, another possibility is to insert a blank or comment somewhere between the opening and closing parens. See the section <a href="#Controlling-List-Formatting">&quot;Controlling List Formatting&quot;</a>.</p>
 
 <h1 id="VERSION">VERSION</h1>
 
-<p>This man page documents perltidy version 20200822</p>
+<p>This man page documents perltidy version 20200907</p>
 
 <h1 id="BUG-REPORTS">BUG REPORTS</h1>
 
index 81fa3cd57b546f795b3a89fbae2aa4f306161126..a7a71819a4569f5c4e288ef2514fee727dde53c9 100644 (file)
@@ -110,7 +110,7 @@ BEGIN {
     # Release version must be bumped, and it is probably past time for a
     # release anyway.
 
-    $VERSION = '20200822';
+    $VERSION = '20200907';
 }
 
 sub streamhandle {
index 16577ca6f3865b549db8d109b798919e68f63898..34e953f5e59248f02bc30eb089334e1d6308803d 100644 (file)
@@ -432,7 +432,7 @@ The module 'Perl::Tidy' comes with a binary 'perltidy' which is installed when t
 
 =head1 VERSION
 
-This man page documents Perl::Tidy version 20200822
+This man page documents Perl::Tidy version 20200907
 
 =head1 LICENSE
 
index e2f210210fc570031f618000775a36ec73f2c092..8dd2c17a523e2b943b32bec4cd73f24308c1bb24 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::Debugger;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index 9a10a3c25542c56d9177e349965f81e57aad0289..2be4a2f59ade26907660c37d238a55fb1f126f52 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::DevNull;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 sub new   { my $self = shift; return bless {}, $self }
 sub print { return }
 sub close { return }
index 518fc1af9d01b887745963dda5a81686de93f6a2..e1c425b67ce99c3b1cadb55b511e062c179d8188 100644 (file)
@@ -20,7 +20,7 @@
 package Perl::Tidy::Diagnostics;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index d898ff419d31625dba06580b085168fd3596e6f9..644b7b1cdc2c657b4e1f8c443b22ba5b34fe57d5 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::FileWriter;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 # Maximum number of little messages; probably need not be changed.
 my $MAX_NAG_MESSAGES = 6;
index 4596c002624a72ad10d829d3d810d83886a7c4b0..2fff8663c42fb8d034d537af21d501346829a3f4 100644 (file)
@@ -12,7 +12,7 @@ package Perl::Tidy::Formatter;
 use strict;
 use warnings;
 use Carp;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 # The Tokenizer will be loaded with the Formatter
 ##use Perl::Tidy::Tokenizer;    # for is_keyword()
@@ -902,8 +902,9 @@ sub keyword_group_scan {
 Unexpected value for -kgbs: '$Opt_size'; expecting 'min' or 'min.max'; 
 ignoring all -kgb flags
 EOM
-       # Turn this option off so that this message does not keep repeating
-       # during iterations and other files.
+
+        # Turn this option off so that this message does not keep repeating
+        # during iterations and other files.
         $rOpts->{'keyword-group-blanks-size'} = "";
         return $rhash_of_desires;
     }
@@ -1232,11 +1233,11 @@ EOM
         ( $K_first, $K_last ) = @{$rK_range};
         if ( !defined($K_first) ) {
 
-            # Unexpected blank line..shouldn't happen
-            # $rK_range should be defined for line type CODE
-            Warn(
-"Programming Error: Unexpected Blank Line in sub 'keyword_group_scan'. Ignoring"
-            );
+            # Somewhat unexpected blank line..
+            # $rK_range is normally defined for line type CODE, but this can
+            # happen for example if the input line was a single semicolon which
+            # is being deleted.  In that case there was code in the input
+            # file but it is not being retained. So we can silently return.
             return $rhash_of_desires;
         }
 
@@ -4623,7 +4624,7 @@ sub non_indenting_braces {
     my @seqno_stack;
 
     my $is_non_indenting_brace = sub {
-        my ($KK)       = @_;
+        my ($KK) = @_;
 
         # looking for an opening block brace
         my $token      = $rLL->[$KK]->[_TOKEN_];
@@ -4631,13 +4632,13 @@ sub non_indenting_braces {
         return unless ( $token eq '{' && $block_type );
 
         # followed by a comment
-        my $K_sc       = $self->K_next_nonblank($KK);
+        my $K_sc = $self->K_next_nonblank($KK);
         return unless defined($K_sc);
         my $type_sc = $rLL->[$K_sc]->[_TYPE_];
         return unless ( $type_sc eq '#' );
 
         # on the same line
-        my $line_index = $rLL->[$KK]->[_LINE_INDEX_];
+        my $line_index    = $rLL->[$KK]->[_LINE_INDEX_];
         my $line_index_sc = $rLL->[$K_sc]->[_LINE_INDEX_];
         return unless ( $line_index_sc == $line_index );
 
@@ -12663,11 +12664,11 @@ sub get_seqno {
         my $rOpts_add_whitespace = $rOpts->{'add-whitespace'};
         my $ralignment_type_to_go;
 
-       # Initialize the alignment array. Note that closing side comments can
-       # insert up to 2 additional tokens beyond the original
-       # $max_index_to_go, so we need to check ri_last for the last index.
+        # Initialize the alignment array. Note that closing side comments can
+        # insert up to 2 additional tokens beyond the original
+        # $max_index_to_go, so we need to check ri_last for the last index.
         my $max_line = @{$ri_first} - 1;
-        my $iend = $ri_last->[$max_line];
+        my $iend     = $ri_last->[$max_line];
         if ( $iend < $max_index_to_go ) { $iend = $max_index_to_go }
         for my $i ( 0 .. $iend ) {
             $ralignment_type_to_go->[$i] = '';
@@ -14861,10 +14862,10 @@ sub pad_array_to_go {
                                 # so don't break before it too
                                 && $i_start_2 ne $i_opening
 
-                                # Defensive coding check: be sure the index is valid.
-                                # FIXME: We should probably be using K indexes for 'starting_index'
-                                # so that the object can remain valid between batches.
-                                # See test problem: random_issues/random_487.pro
+             # Defensive coding check: be sure the index is valid.
+             # FIXME: We should probably be using K indexes for 'starting_index'
+             # so that the object can remain valid between batches.
+             # See test problem: random_issues/random_487.pro
                                 && $i_start_2 >= 0
                                 && $i_start_2 <= $max_index_to_go
                               )
index c5c82c7fa54fcd54fd0d1b322e94b7bb296a6d49..52665f2a513d8fa814572fd06e3a7ad42d6233c5 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::HtmlWriter;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 use File::Basename;
 
index 97b3e8fc0a178afda1d9b4908d2f255d189626cb..3ca49f67db7408a92e42528d194138c767ff2286 100644 (file)
@@ -10,7 +10,7 @@ package Perl::Tidy::IOScalar;
 use strict;
 use warnings;
 use Carp;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
     my ( $package, $rscalar, $mode ) = @_;
index 079faf196b622c9ae98fb78929de8f2f42b9622b..ad5b2c1b0bb101bf8666e2db972d642d170a7f00 100644 (file)
@@ -14,7 +14,7 @@ package Perl::Tidy::IOScalarArray;
 use strict;
 use warnings;
 use Carp;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
     my ( $package, $rarray, $mode ) = @_;
index d69a5b7784af2ea65bb61bba8f94aa4c940c50d0..d65591bd8b9527ecccd1f620ff1ac4da00e44cb8 100644 (file)
@@ -8,7 +8,7 @@
 package Perl::Tidy::IndentationItem;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 BEGIN {
 
index 07ceae28e00b2f0b77eabb235dec9a64e054b233..4117d45237f9902af4479f23b77a4179ef491fea 100644 (file)
@@ -12,7 +12,7 @@
 package Perl::Tidy::LineBuffer;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index e2f6ad8b7de04558cc175a80491a0221da71a3b8..d7ccf72d593e86ac9be316a29316070216190211 100644 (file)
@@ -8,7 +8,7 @@
 package Perl::Tidy::LineSink;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index e5b6e45888a1b13ec99f947985dfcc4e95411f12..4bb1e9ab01b52c1be1a13e312c89562b63e2f6b1 100644 (file)
@@ -8,7 +8,7 @@
 package Perl::Tidy::LineSource;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index 01002e6ec005c3314f27218902a44250a2951e6f..c93ba05b238323c23f667e9aff125b80a4bff9e2 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::Logger;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 sub new {
 
index 898dc741978b89a0f9a88a42e630d12abc19b8ec..1089587ee611affb683d657d9896c3a14fec9045 100644 (file)
@@ -21,7 +21,7 @@
 package Perl::Tidy::Tokenizer;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 use Perl::Tidy::LineBuffer;
 
index 7c799d9e6f47b41113015aeb8eb3c8ef965d723a..36f574633cb6fb52bbe49037751e9aad9d8637bb 100644 (file)
@@ -1,7 +1,7 @@
 package Perl::Tidy::VerticalAligner;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 use Perl::Tidy::VerticalAligner::Alignment;
 use Perl::Tidy::VerticalAligner::Line;
@@ -4137,17 +4137,17 @@ sub get_output_line_number {
         my $line        = $leading_string . $str;
         my $line_length = $leading_string_length + $str_length;
 
-       # Safety check: be sure that a line to be cached as a stacked block
-       # brace line ends in the appropriate opening or closing block brace.
-       # This should always be the case if the caller set flags correctly.
-       # Code '3' is for -sobb, code '4' is for -scbb.
+        # Safety check: be sure that a line to be cached as a stacked block
+        # brace line ends in the appropriate opening or closing block brace.
+        # This should always be the case if the caller set flags correctly.
+        # Code '3' is for -sobb, code '4' is for -scbb.
         if ($open_or_close) {
             if (   $open_or_close == 3 && $line !~ /\{\s*$/
                 || $open_or_close == 4 && $line !~ /\}\s*$/ )
             {
                 $open_or_close = 0;
             }
-        } 
+        }
 
         # write or cache this line
         if ( !$open_or_close || $side_comment_length > 0 ) {
index 1076c68ed3568cc16c11df88d314bd078b7cbfd3..370b95d6b267c1de107bad9092824de039c9d137 100644 (file)
@@ -7,7 +7,7 @@
 package Perl::Tidy::VerticalAligner::Alignment;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 {
 
index 539c13afc50785afeb38869a7d6f10b4efa2904a..1bb014f37a6dbb08981aca1b6501e84ce0984600 100644 (file)
@@ -8,7 +8,7 @@
 package Perl::Tidy::VerticalAligner::Line;
 use strict;
 use warnings;
-our $VERSION = '20200822';
+our $VERSION = '20200907';
 
 {
 
index a44684d6705d98e4dfa16df89a44d90895dffeb0..e214e4baf3e299c6952c85c09b592fce803b5a3e 100755 (executable)
@@ -13,12 +13,16 @@ use warnings;
 # I typically run it in the background from a bash script, something like this
 # nohup nice -n19 perltidy_random_parameters.pl $filename $number
 
+# This creates a lot of output, so run it in a temporary directory and
+# delete everything after checking the results and saving anything noteworthy.
+
 # TODO:
 # - This currently runs the perltidy binary.  Add an option to run call the
 #   module directly.
-# - Add additional garbage strings
-# - The parameters are hardwired but could be obtained directly from perltidy
+# - The parameters are hardwired but should be obtained directly from perltidy
 #   so that they are always up to date.
+# - Simplify the summary: filter essential results to a spreadsheet
+# - Add some additional garbage strings
 
 my $usage = <<EOM;
 Run perltidy repeatedly on a selected file with randomly generated parameters:
@@ -31,143 +35,303 @@ Num is the number of times, default 1000;
 You can stop the run any time by creating a file "stop.now"
 EOM
 
-my $ifile          = $ARGV[0];
-my $ifile_original = $ifile;
-my $max_cases      = $ARGV[1];
-if ( !$ifile || $max_cases <= 0 ) { die "$usage" }
+# 'Chaining' means the next run formats the output of the previous
+# run instead of formatting the original file.
+# 0 = no chaining
+# 1 = always chain unless error
+# 2 = random chaining
+my $CHAIN_MODE = 2;
+
+my @files = @ARGV;
+if ( !@files ) { die "$usage" }
+
+my $max_cases = pop @files;
+if ( $max_cases !~ /^\d+$/ ) {
+    push @files, $max_cases;
+    $max_cases = 100;
+}
+
+if ( !@files ) { die "$usage" }
+my $file_count = 0;
+my $rsummary = [];
+my @problems;
+
+print STDERR <<EOM;
+Chain mode flag: $CHAIN_MODE  (0=no, 1=always, 2=random)
+
+EOM
+
+
 my $stop_file = 'stop.now';
 if ( -e $stop_file ) { unlink $stop_file }
-my $ifile_size = -s $ifile;
-
-# Set this flag to have each run format the output of the previous
-# run instead of formatting the original file.
-my $CHAIN_MODE = 1;
-
-my $case                  = "000";
-my $error_count           = 0;
-my $missing_ofile_count   = 0;
-my $missing_chkfile_count = 0;
-my ( $ofile_size_min,   $ofile_size_max );
-my ( $ofile_case_min,   $ofile_case_max );
-my ( $chkfile_size_min, $chkfile_size_max );
-my ( $chkfile_case_min, $chkfile_case_max );
-my $error_flag    = 0;
-my $restart_count = 0;
-
-for ( 1 .. $max_cases ) {
-    $case += 1;
-    print STDERR "\n-----\nCase: $case\n";
-    print STDOUT "\n-----\nCase: $case\n";
-    my $profile            = "profile.$case";
-    my $rrandom_parameters = get_random_parameters();
-    open OUT, ">", $profile || die "cannot open $profile: $!\n";
-    foreach ( @{$rrandom_parameters} ) {
-        print OUT "$_\n";
-    }
-    close OUT;
-    my $ofile   = "ofile.$case";
-    my $chkfile = "chkfile.$case";
-    system "perltidy < $ifile > $ofile -pro=$profile";
-    my $efile   = "perltidy.ERR";
-    my $logfile = "perltidy.LOG";
-    if ( -e $efile )   { rename $efile,   "ERR.$case" }
-    if ( -e $logfile ) { rename $logfile, "LOG.$case" }
-
-    if ( !-e $ofile ) {
-        print STDERR "**Warning** missing output $ofile\n";
-        $missing_ofile_count++;
-        $error_flag = 1;
-    }
+foreach my $file (@files) {
+    next unless -e $file;
+    $file_count++;
+    my $ifile          = $file;
+    my $ifile_original = $ifile;
+    my $ifile_size = -s $ifile;
+
+    my $case                  = 0;
+    my $error_count           = 0;
+    my $missing_ofile_count   = 0;
+    my $missing_chkfile_count = 0;
+    my ( $ofile_size_min,   $ofile_size_max );
+    my ( $ofile_case_min,   $ofile_case_max );
+    my ( $efile_size_min,   $efile_size_max ) = ( 0,  0 );
+    my ( $efile_case_min,   $efile_case_max ) = ( "", "" );
+    my ( $chkfile_size_min, $chkfile_size_max );
+    my ( $chkfile_case_min, $chkfile_case_max );
+
+    my $error_flag    = 0;
+    my $restart_count = 0;
+    my $efile_count   = 0;
+    my $has_starting_error;
+
+  RUN:
+    for ( 1 .. $max_cases ) {
+        $case += 1;
+        print STDERR "\n-----\nCase $case, File $file_count, File name: '$ifile'\n";
+
+        # Use same random parameters for second and later files..
+        my $profile = "profile.$case";
+        if ( $file_count == 1 ) {
+
+            # use default parameters on first case. That way we can check
+            # if a file produces an error output
+            my $rrandom_parameters;
+            if ( $case > 1 ) {
+                $rrandom_parameters = get_random_parameters();
+            }
+            open OUT, ">", $profile || die "cannot open $profile: $!\n";
+            foreach ( @{$rrandom_parameters} ) {
+                print OUT "$_\n";
+            }
+            close OUT;
+        }
 
-    else {
-        my $ofile_size = -s $ofile;
-        if ( !defined($ofile_size_min) ) {
-            $ofile_size_min = $ofile_size_max = $ofile_size;
-            $ofile_case_min = $ofile_case_max = $ofile;
+        my $ext = $case;
+        if ( @files > 1 ) { $ext .= ".$file_count" }
+        my $fno = @files > 1 ? ".$file_count" : "";
+
+        my $ofile   = "ofile.$ext";
+        my $chkfile = "chkfile.$ext";
+        system "perltidy < $ifile > $ofile -pro=$profile";
+        my $efile   = "perltidy.ERR";
+        my $logfile = "perltidy.LOG";
+        if ( -e $efile )   { rename $efile,   "ERR.$ext" }
+        if ( -e $logfile ) { rename $logfile, "LOG.$ext" }
+
+        if ( !-e $ofile ) {
+            print STDERR "**Warning** missing output $ofile\n";
+            $missing_ofile_count++;
+            $error_flag = 1;
         }
+
         else {
-            if ( $ofile_size < $ofile_size_min ) {
-                $ofile_size_min = $ofile_size;
-                $ofile_case_min = $ofile;
+            my $ofile_size = -s $ofile;
+            if ( !defined($ofile_size_min) ) {
+                $ofile_size_min = $ofile_size_max = $ofile_size;
+                $ofile_case_min = $ofile_case_max = $ofile;
             }
-            if ( $ofile_size > $ofile_size_max ) {
-                $ofile_size_max = $ofile_size;
-                $ofile_case_max = $ofile;
+            else {
+                if ( $ofile_size < $ofile_size_min ) {
+                    $ofile_size_min = $ofile_size;
+                    $ofile_case_min = $ofile;
+                }
+                if ( $ofile_size > $ofile_size_max ) {
+                    $ofile_size_max = $ofile_size;
+                    $ofile_case_max = $ofile;
+                }
             }
         }
-    }
 
-    # run perltidy on the output to see if it can be reformatted
-    # without errors
-    system "perltidy < $ofile > $chkfile";
-    my $err;
-    if ( -e $efile ) {
-        rename $efile, "$chkfile.ERR";
-        print STDERR "**Error reformatting** see $chkfile.ERR\n";
-        $error_count++;
-        $err = 1;
-    }
-    if ( !-e $chkfile ) {
-        print STDERR "**Warning** missing checkfile output $chkfile\n";
-        $missing_chkfile_count++;
-        $err = 1;
-    }
-    else {
-        my $chkfile_size = -s $chkfile;
-        if ( !defined($chkfile_size_min) ) {
-            $chkfile_size_min = $chkfile_size_max = $chkfile_size;
-            $chkfile_case_min = $chkfile_case_max = $chkfile;
+        my $efile_size = 0;
+        if ( -e $efile ) {
+            $efile_size = -s $efile;
+            $efile_count++;
+            if ( !defined($efile_size_min) ) {
+                $efile_size_min = $efile_size_max = $efile_size;
+                $efile_case_min = $efile_case_max = $efile;
+            }
+            else {
+                if ( $efile_size < $efile_size_min ) {
+                    $efile_size_min = $efile_size;
+                    $efile_case_min = $efile;
+                }
+                if ( $efile_size > $efile_size_max ) {
+                    $efile_size_max = $efile_size;
+                    $efile_case_max = $efile;
+                }
+            }
+        }
+
+        # run perltidy on the output to see if it can be reformatted
+        # without errors
+        system "perltidy < $ofile > $chkfile";
+        my $err;
+        if ( -e $efile ) {
+            rename $efile, "$chkfile.ERR";
+            $err = 1;
+            if ($case == 1) {
+                $has_starting_error=1;
+            }
+            elsif ( !$has_starting_error ) {
+                print STDERR "**Error reformatting** see $chkfile.ERR\n";
+                $error_count++;
+            }
+        }
+        if ( !-e $chkfile ) {
+            print STDERR "**Warning** missing checkfile output $chkfile\n";
+            $missing_chkfile_count++;
+            $err = 1;
         }
         else {
-            if ( $chkfile_size < $chkfile_size_min ) {
-                $chkfile_size_min = $chkfile_size;
-                $chkfile_case_min = $chkfile;
+            my $chkfile_size = -s $chkfile;
+            if ( !defined($chkfile_size_min) ) {
+                $chkfile_size_min = $chkfile_size_max = $chkfile_size;
+                $chkfile_case_min = $chkfile_case_max = $chkfile;
+            }
+            else {
+                if ( $chkfile_size < $chkfile_size_min ) {
+                    $chkfile_size_min = $chkfile_size;
+                    $chkfile_case_min = $chkfile;
+                }
+                if ( $chkfile_size > $chkfile_size_max ) {
+                    $chkfile_size_max = $chkfile_size;
+                    $chkfile_case_max = $chkfile;
+                }
             }
-            if ( $chkfile_size > $chkfile_size_max ) {
-                $chkfile_size_max = $chkfile_size;
-                $chkfile_case_max = $chkfile;
+        }
+
+        $ifile = $ifile_original;
+        if ( $CHAIN_MODE && !$err ) {
+            if ( $CHAIN_MODE == 1 || int( rand(1) + 0.5 ) ) {
+                { $ifile = $ofile }
             }
         }
+
+        if ( -e $stop_file ) {
+            print STDERR "$stop_file seen; exiting\n";
+            last RUN;
+        }
     }
 
-    if ($CHAIN_MODE) {
-        $ifile = $err ? $ifile_original : $ofile;
-        $restart_count++ if ($err);
+    $rsummary->[$file_count] = {
+        input_name            => $ifile_original,
+        input_size            => $ifile_size,
+        error_count           => $error_count,
+        efile_count           => $efile_count,
+        missing_ofile_count   => $missing_ofile_count,
+        missing_chkfile_count => $missing_chkfile_count,
+        minimum_output_size   => $ofile_size_min,
+        maximum_output_size   => $ofile_size_max,
+        minimum_output_case   => $ofile_case_min,
+        maximum_output_case   => $ofile_case_max,
+        minimum_rerun_size    => $chkfile_size_min,
+        maximum_rerun_size    => $chkfile_size_max,
+        minimum_rerun_case    => $chkfile_case_min,
+        maximum_rerun_case    => $chkfile_case_max,
+        minimum_error_size    => $efile_size_min,
+        maximum_error_size    => $efile_size_max,
+        minimum_error_case    => $efile_case_min,
+        maximum_error_case    => $efile_case_max,
+    };
+
+    report_results($rsummary->[$file_count]);
+
+    # Save anything that looks like it needs attention
+    if (   $error_count
+        || $missing_ofile_count
+        || $missing_chkfile_count
+        || $ofile_size_min == 0
+        || $chkfile_size_min == 0 )
+    {
+        push @problems, $file_count;
     }
 
-    if ( -e $stop_file ) {
-        print STDERR "$stop_file seen; exiting\n";
+} # End loop over files
+
+if (@problems) {
+    print STDERR <<EOM;
+
+=============================
+SUMMARY OF POSSIBLE PROBLEMS:
+=============================
+EOM
+
+    foreach my $nf (@problems) {
+        report_results( $rsummary->[$nf] );
     }
 }
+else {
+    print STDERR <<EOM;
+
+========================
+No obvious problems seen
+========================
+EOM
+
+}
 
-# Report results
-my $mode =
-  $CHAIN_MODE ? "chain mode, $restart_count restarts" : 'non-chain mode';
 print STDERR <<EOM;
-Run Summary:
-$ifile_original: starting input file
-running in $mode
+
+Be sure to search STDERR for 'uninitialized' and other warnings
+EOM
+
+
+sub report_results {
+
+    my ( $rh ) = @_;
+
+    my $ifile_original        = $rh->{input_name};
+    my $ifile_size            = $rh->{input_size};
+    my $error_count           = $rh->{error_count};
+    my $efile_count           = $rh->{efile_count};
+    my $missing_ofile_count   = $rh->{missing_ofile_count};
+    my $missing_chkfile_count = $rh->{missing_chkfile_count};
+    my $ofile_size_min        = $rh->{minimum_rerun_size};
+    my $ofile_size_max        = $rh->{maximum_rerun_size};
+    my $ofile_case_min        = $rh->{minimum_rerun_case};
+    my $ofile_case_max        = $rh->{maximum_rerun_case};
+    my $chkfile_size_min      = $rh->{minimum_output_size};
+    my $chkfile_size_max      = $rh->{maximum_output_size};
+    my $chkfile_case_min      = $rh->{minimum_output_case};
+    my $chkfile_case_max      = $rh->{maximum_output_case};
+    my $efile_size_min        = $rh->{minimum_error_size};
+    my $efile_size_max        = $rh->{maximum_error_size};
+    my $efile_case_min        = $rh->{minimum_error_case};
+    my $efile_case_max        = $rh->{maximum_error_case};
+
+    print STDERR <<EOM;
+Results summary for Input File: '$ifile_original'
+Size : $ifile_size
 $error_count files had errors when reformatted
 $missing_ofile_count output files were missing 
 $missing_chkfile_count check output files were missing
-
-Size of test file: $ifile_size
 EOM
 
-print STDERR <<EOM if ( defined($ofile_size_min) );
+    print STDERR <<EOM if ( defined($ofile_size_min) );
+
 Minimum output size: $ofile_size_min for case $ofile_case_min
 Maximum output size: $ofile_size_max for case $ofile_case_max
 EOM
 
-print STDERR <<EOM if ( defined($chkfile_size_min) );
+    print STDERR <<EOM if ( defined($chkfile_size_min) );
+
 Minimum rerun size: $chkfile_size_min for case $chkfile_case_min
 Maximum rerun size: $chkfile_size_max for case $chkfile_case_max
 EOM
 
-print STDERR <<EOM;
+    print STDERR <<EOM if ( defined($efile_size_min) );
 
-Be sure to search for 'unitialized' in STDERR
+Number of error files: $efile_count 
+Minimum error file size: $efile_size_min for case $efile_case_min
+Maximum error file size: $efile_size_max for case $efile_case_max
 EOM
+    return;
+}
+
+
 
 sub get_random_parameters {
 
@@ -479,7 +643,8 @@ sub get_random_parameters {
         ':s' => 'OPTIONAL STRING',
     );
 
-    my @random_words = qw(bannanas sub train apples);
+    my @random_words = qw(bannanas sub subaru train 1x =+ !);
+
     my @operators =
       qw(% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=);
     my @keywords = qw(my our local do while if  garbage1 34 );
@@ -545,13 +710,12 @@ sub get_random_parameters {
         'default-tabsize'          => [ 0, 8 ],
         'entab-leading-whitespace' => [ 0, 8 ],
 
-        # TODO: FILL thESE with multiple random operators
-        'want-break-after'   => \@operators,    #['+', '-', '*', '=', '.'],
-        'want-break-before'  => \@operators,    #['+', '-', '*'],
-        'want-left-space'    => \@operators,    #['+', '-', '*'],
-        'want-right-space'   => \@operators,    #['+', '-', '*'],
-        'nowant-left-space'  => \@operators,    #['+', '-', '*'],
-        'nowant-right-space' => \@operators,    #['+', '-', '*'],
+        'want-break-after'   => \@operators,
+        'want-break-before'  => \@operators,
+        'want-left-space'    => \@operators,
+        'want-right-space'   => \@operators,
+        'nowant-left-space'  => \@operators,
+        'nowant-right-space' => \@operators,
 
         #'keyword-group-blanks-list=s
         'keyword-group-blanks-size' => [ 0, 2, 4, 7, 10, 2.8, 1.8 ],
@@ -619,10 +783,21 @@ sub get_random_parameters {
       html
       notidy
       format
+      help
+      version
       starting-indentation-level
       tee-block-comments
       tee-pod
       tee-side-comments
+      dump-cuddled-block-list
+      dump-defaults
+      dump-long-names
+      dump-options
+      dump-profile
+      dump-short-names
+      dump-token-types
+      dump-want-left-space
+      dump-want-right-space
     );
 
     my %skip;
@@ -706,30 +881,3 @@ sub get_random_parameters {
     }
     return \@random_parameters;
 }
-
-sub get_num {
-    my ( $msg, $default ) = @_;
-    if ( defined($default) ) {
-        $msg =~ s/:$//;
-        $msg .= " (<cr>=$default):";
-    }
-    my $ans = query($msg);
-    $ans = $default if ( defined($default) && $ans eq "" );
-    my $val = eval($ans);
-    if ($@) { warn $@; $val = $ans; }
-    return $val;
-}
-
-sub queryu {
-    return uc query(@_);
-}
-
-sub query {
-    my ($msg) = @_;
-    print $msg;
-    my $ans = <STDIN>;
-    chomp $ans;
-
-    #my $val=$ans;
-    return $ans;
-}