From 7044637b6122507ea4d4f0fdaf0e255adf105055 Mon Sep 17 00:00:00 2001 From: Michael Mikonos <127171689+mknos@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:16:06 +0800 Subject: [PATCH] tsort: pairs can split across lines * The previous commit handled the problem of odd input tokens being ignored, but tsort still rejects some valid input * Exit with failure code if close() failed, after printing output * Allow a single token on a line; this is valid as long as the total number of tokens is even * Tested against GNU version %printf "a b\nb\n c\n\n" > in.tsort %tsort in.tsort # tsort (GNU coreutils) 8.32 a b c %perl tsort in.tsort # with patch applied a b c %perl ~/PerlPowerTools.old/bin/tsort in.tsort # from older commit 9d4efce79c655d6075da0d3f71b35d228056903c which gets it totally wrong a b --- bin/tsort | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/bin/tsort b/bin/tsort index cf400d4d..4a018dfd 100755 --- a/bin/tsort +++ b/bin/tsort @@ -49,27 +49,28 @@ if ($file eq '-') { my %pairs; # all pairs ($l, $r) my %npred; # number of predecessors my %succ; # list of successors +my @input; while (<$fh>) { next unless m/\w/; + s/\A\s+//; + s/\s+\z//; my @l = split; - next unless scalar(@l); - - if (scalar(@l) % 2 == 1) { - warn "$Program: odd number of tokens on line $.\n"; - exit EX_FAILURE; - } - while (@l) { - my $l = shift @l; - my $r = shift @l; - next if defined $pairs{$l}{$r}; - $pairs{$l}{$r}++; - $npred{$l} += 0; - ++$npred{$r}; - push @{$succ{$l}}, $r; - } + push @input, @l if scalar(@l); +} +if (scalar(@input) % 2 == 1) { + warn "$Program: odd number of tokens\n"; + exit EX_FAILURE; +} +while (@input) { + my $l = shift @input; + my $r = shift @input; + next if defined $pairs{$l}{$r}; + $pairs{$l}{$r}++; + $npred{$l} += 0; + ++$npred{$r}; + push @{$succ{$l}}, $r; } -close $fh; # create a list of nodes without predecessors my @list = grep {!$npred{$_}} keys %npred; @@ -88,6 +89,10 @@ while (@list) { } warn "$Program: cycle detected\n" if grep {$npred{$_}} keys %npred; +unless (close $fh) { + warn "$Program: failed to close input: $!\n"; + exit EX_FAILURE; +} exit EX_SUCCESS; sub usage {