376 lines
7.1 KiB
Perl
Executable File
376 lines
7.1 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2004-2007 Jan Engelhardt
|
|
#
|
|
# wktimer
|
|
# A program which impelements time() based time counters.
|
|
#
|
|
use Getopt::Long;
|
|
use constant {
|
|
OP_RESTAMP => 1 << 0,
|
|
OP_VERBOSE => 1 << 1,
|
|
};
|
|
use strict;
|
|
no strict "subs"; # OP_START/OP_STOP
|
|
|
|
my $do_show = 1;
|
|
my $g_flags = OP_VERBOSE;
|
|
my $flag_iStart = 0;
|
|
my $flag_hdr = 1;
|
|
my $flag_sec = 0;
|
|
my $timer_file = $ENV{HOME}."/.timers";
|
|
my @ARGV2;
|
|
my %TIMER;
|
|
|
|
sub repush {
|
|
push(@ARGV2, "-".shift(@_), @_);
|
|
return;
|
|
}
|
|
&Getopt::Long::Configure(qw(bundling pass_through));
|
|
&GetOptions(
|
|
"A|add=s" => \&repush,
|
|
"D|del|delete=s" => \&repush,
|
|
"F|flush" => \&repush,
|
|
"H|nohdr" => sub { $flag_hdr = 0; },
|
|
"L|list:s" => \&repush,
|
|
"S|stop=s" => \&repush,
|
|
"X=s" => \&repush,
|
|
"W|switch=s" => \&repush,
|
|
"i|istart" => \$flag_iStart,
|
|
"q|quiet" => sub { $g_flags &= ~OP_VERBOSE; },
|
|
"s|sec" => \$flag_sec,
|
|
"t|file=s" => \$timer_file,
|
|
);
|
|
|
|
&read_timers($g_flags);
|
|
@ARGV = @ARGV2;
|
|
|
|
&GetOptions(
|
|
"A|add=s" => sub {
|
|
$do_show = 0;
|
|
foreach my $name (split(/,/so, $_[1])) {
|
|
&start_timer($name, OP_RESTAMP | $g_flags);
|
|
}
|
|
},
|
|
"D|del|delete=s" => sub {
|
|
$do_show = 0;
|
|
foreach my $name (split(/,/so, $_[1])) {
|
|
&delete_timer($name, OP_RESTAMP | $g_flags);
|
|
}
|
|
},
|
|
"F|flush" => sub {
|
|
$do_show = 0;
|
|
&flush_timers($g_flags);
|
|
},
|
|
"L|list:s" => sub {
|
|
$do_show = 0;
|
|
&show_timers(split(/,/so, $_[1]));
|
|
},
|
|
"S|stop=s" => sub {
|
|
$do_show = 0;
|
|
foreach my $name (split(/,/so, $_[1])) {
|
|
&stop_timer($name, $g_flags);
|
|
}
|
|
},
|
|
"X=s" => sub {
|
|
foreach my $name (split(/,/so, $_[1])) {
|
|
&stop_timer($name, OP_RESTAMP | $g_flags);
|
|
}
|
|
},
|
|
"W|switch=s" => sub {
|
|
$do_show = 0;
|
|
foreach my $name (split(/,/so, $_[1])) {
|
|
&switch_timer($name, $g_flags);
|
|
}
|
|
},
|
|
);
|
|
|
|
if ($do_show) {
|
|
&show_timers();
|
|
}
|
|
&save_timers($g_flags);
|
|
|
|
sub start_timer ()
|
|
{
|
|
my $name = lc shift @_;
|
|
my $flags = shift @_;
|
|
|
|
if (!exists($TIMER{$name})) {
|
|
$TIMER{$name} = {};
|
|
my $t = $TIMER{$name};
|
|
$t->{InitialStart} = $t->{Start} = time();
|
|
$t->{Stop} = -1;
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Created timer \"$name\"\n";
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
my $t = $TIMER{$name};
|
|
if ($t->{Stop} < 0 && $flags & OP_RESTAMP) {
|
|
# still running
|
|
$t->{Stop} = time();
|
|
$t->{Cumulative} += $t->{Stop} - $t->{Start};
|
|
$t->{Start} = $t->{Stop};
|
|
$t->{Stop} = -1;
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Updated START mark for timer \"$name\"\n";
|
|
}
|
|
} elsif ($t->{Stop} >= 0) {
|
|
# was a stopped timer
|
|
$t->{Start} = time();
|
|
$t->{Stop} = -1;
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Restarted timer \"$name\"\n";
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub stop_timer ()
|
|
{
|
|
my $name = lc shift @_;
|
|
my $flags = shift @_;
|
|
|
|
if (!exists($TIMER{$name})) {
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Timer \"$name\" does not exist\n";
|
|
}
|
|
return;
|
|
}
|
|
|
|
my $t = $TIMER{$name};
|
|
if ($t->{Stop} >= 0 && $flags & OP_RESTAMP) {
|
|
$t->{Cumulative} -= $t->{Stop} - $t->{Start};
|
|
$t->{Stop} = time();
|
|
$t->{Cumulative} += $t->{Stop} - $t->{Start};
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Updated STOP mark for timer \"$name\"\n";
|
|
}
|
|
} elsif ($t->{Stop} < 0) {
|
|
$t->{Stop} = time();
|
|
$t->{Cumulative} += $t->{Stop} - $t->{Start};
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Stopped timer \"$name\"\n";
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub switch_timer ()
|
|
{
|
|
my $name = lc shift @_;
|
|
my $flags = shift @_;
|
|
|
|
if (!exists($TIMER{$name})) {
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Timer \"$name\" does not exist\n";
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
foreach my $subname (keys %TIMER) {
|
|
my $t = $TIMER{$subname};
|
|
if ($subname ne $name) {
|
|
&stop_timer($subname, OP_STOP);
|
|
} else {
|
|
&start_timer($name, OP_START);
|
|
}
|
|
}
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Switched to timer \"$name\"\n";
|
|
}
|
|
&save_timers();
|
|
return;
|
|
}
|
|
|
|
sub delete_timer ()
|
|
{
|
|
my $name = lc shift @_;
|
|
my $flags = shift @_;
|
|
|
|
if (exists $TIMER{$name}) {
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Timer \"$name\" does not exist\n";
|
|
}
|
|
return;
|
|
}
|
|
delete $TIMER{$name};
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Deleted timer \"$name\"\n";
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub flush_timers ()
|
|
{
|
|
my $flags = shift @_;
|
|
undef %TIMER;
|
|
if ($flags & OP_VERBOSE) {
|
|
print "Deleted all timers\n";
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub read_timers()
|
|
{
|
|
local *IN;
|
|
|
|
if (!-e $timer_file) {
|
|
return;
|
|
}
|
|
|
|
open(IN, "< $timer_file") || die "Could not open $timer_file: $!\n";
|
|
|
|
while (defined(my $ln = <IN>)) {
|
|
my($name, @data);
|
|
my $t;
|
|
|
|
chomp($ln);
|
|
$ln =~ s/^\s+//giso;
|
|
$ln =~ s/\s+$//giso;
|
|
($name, @data) = split(/\s+/, $ln);
|
|
$TIMER{$name} = {};
|
|
$t = $TIMER{$name};
|
|
$t->{InitialStart} = shift @data;
|
|
$t->{Cumulative} = shift @data;
|
|
$t->{Start} = shift @data;
|
|
$t->{Stop} = shift @data;
|
|
}
|
|
|
|
close IN;
|
|
return;
|
|
}
|
|
|
|
sub show_timers ()
|
|
{
|
|
if ($flag_hdr) {
|
|
printf "%-10s", "Name";
|
|
if ($flag_iStart) {
|
|
printf " %11s", "I-Start";
|
|
}
|
|
printf " %12s %11s %11s %12s\n",
|
|
"Cumulative", "L-Start", "L-Stop", "Elapsed";
|
|
}
|
|
|
|
if ($#_ >= 0) {
|
|
foreach my $name (@_) {
|
|
$name = lc $name;
|
|
if (exists $TIMER{$name}) {
|
|
&print_timer($name);
|
|
}
|
|
}
|
|
} else {
|
|
foreach my $name (sort keys %TIMER) {
|
|
&print_timer($name);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub print_timer ()
|
|
{
|
|
my $name = shift @_;
|
|
my $t = $TIMER{$name};
|
|
my $cum = ($t->{Cumulative} + (($t->{Stop} == -1) ?
|
|
time() - $t->{Start} : 0));
|
|
my $elap = time() - $t->{Start};
|
|
|
|
if ($flag_sec) {
|
|
$cum .= "s";
|
|
$elap .= "s";
|
|
} else {
|
|
$cum = &sec2dur($cum);
|
|
$elap = &sec2dur($elap);
|
|
}
|
|
|
|
printf "%-10s", $name;
|
|
if ($flag_iStart) {
|
|
printf " %11s", &sec2date($t->{InitialStart});
|
|
}
|
|
printf " %12s %11s %11s %12s\n",
|
|
$cum, &sec2date($t->{Start}), &sec2date($t->{Stop}), $elap;
|
|
return;
|
|
}
|
|
|
|
sub save_timers ()
|
|
{
|
|
local *OUT;
|
|
|
|
if (scalar(keys %TIMER) == 0) {
|
|
unlink $timer_file;
|
|
return;
|
|
}
|
|
|
|
open(OUT, "> $timer_file") || die "Could not open $timer_file: $!\n";
|
|
|
|
foreach my $name (sort keys %TIMER) {
|
|
my %t = %{$TIMER{$name}};
|
|
printf OUT "%s %u %u %u %d\n",
|
|
$name, @t{InitialStart,Cumulative,Start,Stop};
|
|
}
|
|
close OUT;
|
|
return;
|
|
}
|
|
|
|
sub is_running ()
|
|
{
|
|
my $name = lc shift @_;
|
|
if ($TIMER{$name}{Stop} < 0) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub sec2date ()
|
|
{
|
|
my $in = shift @_;
|
|
if ($in < 0) {
|
|
return "(running)";
|
|
}
|
|
my @d = localtime $in;
|
|
return sprintf "%02d%02d-%02d%02d%02d", $d[3], $d[4] + 1, @d[2,1,0];
|
|
}
|
|
|
|
sub sec2dur ()
|
|
{
|
|
my($S_hr, $S_min, $S_sec) = (0, 0, 0);
|
|
my $in = shift @_;
|
|
my $sec = $in % 60;
|
|
my $min = int($in / 60) % 60;
|
|
my $hr = int($in / 3600) % 24;
|
|
my $days = int($in / 86400);
|
|
my $ret;
|
|
|
|
if ($days != 0) {
|
|
$ret .= sprintf "%dd", $days;
|
|
$S_hr = $S_min = $S_sec = 2;
|
|
}
|
|
|
|
if ($hr != 0 || $S_hr) {
|
|
if ($S_hr == 2) {
|
|
$ret .= sprintf "%02dh", $hr;
|
|
} else {
|
|
$ret .= sprintf "%2dh", $hr;
|
|
}
|
|
$S_min = $S_sec = 2;
|
|
}
|
|
|
|
if ($min != 0 || $S_min) {
|
|
if ($S_min == 2) {
|
|
$ret .= sprintf "%02dm", $min;
|
|
} else {
|
|
$ret .= sprintf "%2dm", $min;
|
|
}
|
|
$S_sec = 2;
|
|
}
|
|
|
|
if ($S_sec == 2) {
|
|
$ret .= sprintf "%02ds", $sec;
|
|
} else {
|
|
$ret .= sprintf "%2ds", $sec;
|
|
}
|
|
|
|
return $ret;
|
|
}
|