Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

ilf - input line frequency time event visualization

by cider (Acolyte)
on Jul 13, 2005 at 00:28 UTC ( [id://474423]=sourcecode: print w/replies, xml ) Need Help??
Category:
Author/Contact Info steven fountain (slf@dreamscape.org) http://dreamscape.org/code/ (http://dreamscape.org/steven-fountain.txt) 1-925-895-1500
Description: --------------------------------------------------------
screenshots @ http://dreamscape.org/code/ilf-war.png
inspiration @ http://dreamscape.org/swim/index.php/article/112089231
++ instant war room ++
(using xterm's) http://dreamscape.org/code/ilf-war
(using eterm's) http://dreamscape.org/code/ilf-war-eterm
this version is capable of much much more:)
--------------------------------------------------------
get it at http://dreamscape.org/code/ilf
-------------------------------------------------------------------- ilf - input line frequency/time event visualization DSC Ops Research Group - http://dreamscape.org/ (slf@) organicly evolved from: http://dreamscape.org/code/tdpc -------------------------------------------------------------------- you will see two things: symbols that show timechanges (also indicating a line was seen), and secondly symbols that happen so quickly a timechange has not happened. you can customize the colors of each of these w/ -c -t -------------------------------------------------------------------- psuedo-math for 'blinky light over time' w/ducttape it all started because I pondered to myself . o O "I wonder how frequently I make my neighbors w/love:) wireless light blink.." ..then it evolved! -------------------------------------------------------------------- screenshots of its predecessor's output can be found at http://dreamscape.org/swim/index.php/article/1120892317 this version is capable of much much more:) screenshots @ http://dreamscape.org/code/ilf-war.png >> instant war room << (using xterm's) http://dreamscape.org/code/ilf-war (using eterm's) http://dreamscape.org/code/ilf-war-eterm -------------------------------------------------------------------- General options: -b 'REGEX' pattern that allways triggers bold -i 'REGEX' pattern that allways triggers reverse -F 'REGEX' pattern that allways triggers blink -r 'REGEX' pattern that triggers reverse ON -R 'REGEX' pattern that triggers reverse OFF -k 'REGEX' pattern that triggers blinking ON -K 'REGEX' pattern that triggers blinking OFF -f 'STR' color choice for "he's on fire!" mode -L INT the limit that triggers "he's on fire!" mode (the default is 50 within .1s (1 ms)) -l enable internal logging to ilf.log (ilf | tee -a ilf.log.color is cooler) -m INT number of lines to represent on each line in our visualization (the default is 50) -c 'STR' color choice for really fast lines -t 'STR' color choice for time changes -h display this help -H drop this help text to ilf.txt and less it -z FLOAT sleep this much time instead of default 1s "builtin" function: -N [-n[O]] [-d] : track output of lsof (network status) -S [-n[O]] [-d] : track output of lsof (system status) -W [-n[0]] [-d] : track output of who (login activity) -s [-n[O]] [-d] : track output of ps auxfw (process activity) -D 'command line' [-n[o]] [-d] : track "command" output Usage: ilf 'command line' ilf -- command [args ...] ilf -d command [args ...] (is equivilant to -- but with debug) ilf builtin {-D|-N|-S|-W|-s} [options ...] ilf builtin -D 'tail -1000 /var/log/*.log' -n ilf -w ilf -H
#!/usr/bin/perl
# ilf - input line frequency/time event visualization (slf@dreamscape.
+org)
#                a steven fountain creation most definitely:) hire me?
#                  i do it all for the praise and the word of mouth
#
# psuedo-math for 'blinky light over time' w/duct tape for general uni
+xy things
#
# screenshots of its predecessor's output at http://dreamscape.org/swi
+m/index.php/article/1120892317
# this version is capable of much much more:)
# >> instant war room <<
#      screenshots @ http://dreamscape.org/code/ilf-war.png
#    (using xterm's) http://dreamscape.org/code/ilf-war
#    (using eterm's) http://dreamscape.org/code/ilf-war-eterm
#
# Come back later and check out this file again at http://dreamscape.o
+rg/code/ilf
# as it may be updated and improved!
#
$usage = "------------------------------------------------------------
+--------
   ilf - input line frequency/time event visualization
  DSC Ops Research Group - http://dreamscape.org/ (slf@)
 organicly evolved from: http://dreamscape.org/code/tdpc
--------------------------------------------------------------------
 you will see two things: symbols that show timechanges
 (also indicating a line was seen), and secondly symbols
 that happen so quickly a timechange has not happened.
 you can customize the colors of each of these w/ -c -t
--------------------------------------------------------------------
  psuedo-math for 'blinky light over time' w/ducttape
          it all started because I pondered to myself
   . o O \"I wonder how frequently I make my neighbors
w/love:)  wireless light blink..\"    ..then it evolved!
--------------------------------------------------------------------
 screenshots of its predecessor's output can be found at
 http://dreamscape.org/swim/index.php/article/1120892317
 this version is capable of much much more:)
 screenshots @ http://dreamscape.org/code/ilf-war.png
 >> instant war room <<
    (using xterm's) http://dreamscape.org/code/ilf-war
    (using eterm's) http://dreamscape.org/code/ilf-war-eterm
--------------------------------------------------------------------
  General options:
   -b 'REGEX' pattern that allways triggers bold
   -i 'REGEX' pattern that allways triggers reverse
   -F 'REGEX' pattern that allways triggers blink
   -r 'REGEX' pattern that triggers reverse ON
   -R 'REGEX' pattern that triggers reverse OFF
   -k 'REGEX' pattern that triggers blinking ON
   -K 'REGEX' pattern that triggers blinking OFF
   -f 'STR'   color choice for \"he's on fire!\" mode
   -L INT     the limit that triggers \"he's on fire!\" mode
              (the default is 50 within .1s (1 ms))
   -l         enable internal logging to ilf.log
              ($0 | tee -a ilf.log.color is cooler)
   -m INT     number of lines to represent on each line in
              our visualization (the default is 50)
   -c 'STR'   color choice for really fast lines
   -t 'STR'   color choice for time changes
   -h         display this help
   -H         drop this help text to ilf.txt and less it
   -z FLOAT   sleep this much time instead of default 1s

  \"builtin\" function:
   -N [-n[O]] [-d] : track output of lsof (network status)
   -S [-n[O]] [-d] : track output of lsof (system status)
   -W [-n[0]] [-d] : track output of who (login activity)
   -s [-n[O]] [-d] : track output of ps auxfw (process activity)
   -D 'command line' [-n[o]] [-d] : track \"command\" output

 Usage:
   $0 'command line'
   $0 -- command [args ...]
   $0 -d command [args ...] (is equivilant to -- but with debug)
   $0 builtin {-D|-N|-S|-W|-s} [options ...]
   $0 builtin -D 'tail -1000 /var/log/*.log' -n
   $0 -w
   $0 -H                                           
";


use Term::ANSIColor;
use Time::HiRes qw(time);
$|=1; # autoflushing (required)
use Getopt::Std;
$specificly = shift || die "$usage";
if ($specificly =~ /^-H/)
{
  open HELP, "> ilf.txt";
  print HELP "$usage";
  close HELP;
  system "less ilf.txt";
  print "The help file exists as ilf.txt if you need to refer to it ag
+ain.\n";
  exit;
}

sub printandorlog
{ # no color for the log, sorry ;) just perl ilf -- blah | tee -a ilf.
+log.color
  my $msg=shift;
  print "$msg";
  print LOG "$msg" if ($l eq 1);
}

if ($specificly eq '-d')
{
  printandorlog "# Letting you get away with ghetto option evading. ;)
+\n";
  $specificly = join ' ', @ARGV;
  printandorlog "# Enabling debugging too. This is the only option you
+ get. ;);)\n";
  $d = 1;
}
elsif ($specificly eq '-w')
{
  print "Retrieving http://dreamscape.org/code/ilf-war to ./ilf-war ..
+\n";
  system "wget -O ilf-war http://dreamscape.org/code/ilf-war";
  
  print "Adding execute bit to ./ilf-war ..\n";
  system "chmod +x ilf-war";
  
  print "Running ./ilf-war ..\n";
  system "./ilf-war &";
  
  exit;
}
elsif ($specificly eq '--')
{
  printandorlog "# Letting you get away with ghetto option evading. ;)
+\n";
  $specificly = join ' ', @ARGV;
}
else
{
  getopts('i:b:K:k:m:c:t:D:F:r:R:L:hlsdSNWnoHwz', \%switches);
  (print "$usage" and exit) if ($specificly =~ /^-(?:h|help|\-help)(?:
+$|\s)/);
  foreach(sort keys %switches) {
    $usedaswitch=1;
    ${$_}= "$switches{$_}";
    (print "$usage" and exit) if ($h eq 1);
    #warn "# * Hint: -D usage is supposed to be something like -D 'tai
+l /var/log/messages' and NOT 'tail -f /var/log/messages'\n *        M
+aybe you might want $0 \'$D\' instead if you dont see changes.\n" if 
+($D && $D =~ /(?:tail|tcpdump|watch)/);
    printandorlog "#  * $_ is \"$switches{$_}\"";
    if ($switches{$_} eq '1') { printandorlog " (ON)"; }
    if ($switches{$_} eq '0') { printandorlog " (OFF)"; }
    printandorlog "\n";
  }
}

if ($l eq 1)
{ 
  system "mv ilf.log.2ago ilf.log.3ago 2>/dev/null";
  system "mv ilf.log.1ago ilf.log.2ago 2>/dev/null";
  system "mv ilf.log      ilf.log.1ago 2>/dev/null";
  die "I tried to move ilf.log out of the way but it's still there?  Y
+o?\n" if (-e "ilf.log");
  open LOG, "+>> ilf.log" or die "Cant create ilf.log, given reason is
+: $!\n";
  printandorlog "# Logging enabled to ilf.log\n";
}

$SLEEP=$z || "1s"; # the number of seconds to sleep when diffing outpu
+t
$max=$m || 50;    # the number of lines to represent on one line
$hesonfire=$L || 50; # the number of lines that trigger the special "h
+e's on fire!" mode
$reallyfastcolor = $c || "blue";  #(items within the same second are d
+isplayed as this color)
$hesonfirecolor  = $f || "red"; #(items that have triggered the "he's 
+on fire!" mode are displayed as this color)
$timechangecolor = $t || "cyan";  #(time changes are represented by th
+is color)
$na = " - - NOT APPLICABLE - - (?: never..) "; #(hopefully you arent r
+unning ilf 'cat ilf' ? ;)
$blinkon = $k || $na;
$blinkoff = $K || $na;
$reverseon = $r || $na;
$reverseoff = $R || $na;
$whenbold = $b || $na;
$whenreverse = $i || $na;
$whenblink = $F || $na;

$blinkon =~ /NOT APPLICABLE/     ? 1 : printandorlog "                
+  pattern that hilights everything bold: /$whenbold/\n";
$blinkoff =~ /NOT APPLICABLE/    ? 1 : printandorlog "               p
+attern that hilights everything reverse: /$whenreverse/\n";
$whenbold =~ /NOT APPLICABLE/    ? 1 : printandorlog " pattern that fl
+ips the blink switch to the ON position: /$blinkon/\n";
$whenreverse =~ /NOT APPLICABLE/ ? 1 : printandorlog "pattern that fli
+ps the blink switch to the OFF position: /$blinkoff/\n";
$c eq '' ? 1 : printandorlog "reallyfastcolor: $reallyfastcolor\n";
$t eq '' ? 1 : printandorlog "timechangecolor: $timechangecolor\n";

$char = ">"; # input lines are flowing character (if you see nothing b
+ut these, we never successfully encoded a symbol)
$otime = " "; # intialize it to something so NEW!=OLD works w/no bs
$oldsize = 0; # initializing the byte-counter & byte-incremental math

if ($n eq 1 && $o eq 1) { $diffmethod = '[<>]'; }
elsif ($n eq 1) { $diffmethod = '>'; }
elsif ($o eq 1) { $diffmethod = '<'; }
else { $diffmethod = '[<>]'; }

# control-C binding
$SIG{INT} = sub { close LOG if $l; die " <- ok, exiting.\n"; };
# open TD, "tcpdump -n -i $device -s 2000 -l $specificly 2>/dev/null |
+" or die "cannot open $specificly because of: $!\n";
sub rndStr{local $"=''; "@_[map{rand$#_} 1 .. shift]"; }
$magic = `mcookie 2> /dev/null && date 2> /dev/null` || rndStr 16, 'A'
+..'Z', 0..9, 'a-z';
$magic =~ s/\n/__/g;
$magic =~ s/ /_/g;
if ($s eq 1 && $specificly eq 'builtin') { $specificly = "while true; 
+do mv /tmp/diff.now.$magic /tmp/.diff.then.$magic ; ps auxfw | grep -
+v auxfw | grep -v grep | grep -v builtin | grep -v sleep > /tmp/diff.
+now.$magic 2> /dev/null ; diff /tmp/.diff.then.$magic /tmp/diff.now.$
+magic 2>/dev/null | grep \"^$diffmethod\" 2> /dev/null ; sleep ${SLEE
+P}; done"; }
if (defined $D && $specificly eq 'builtin') { open DTEST, "$D 2\>\&1 |
+" or die "couldnt execute $D: $!\n"; close DTEST; $specificly = "whil
+e true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2> /de
+v/null ; $D > /tmp/.custom.now.$magic 2> /dev/null ; diff /tmp/.custo
+m.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmethod\" 2> /dev
+/null ; sleep ${SLEEP}; done"; }
if (defined $N && $specificly eq 'builtin') { open LSOF, "lsof -n 2\>\
+&1 |" or die "couldnt execute lsof: $!\n"; close LSOF; $specificly = 
+"while true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2
+> /dev/null ; lsof -i -n > /tmp/.custom.now.$magic 2> /dev/null ; dif
+f /tmp/.custom.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmet
+hod\" 2> /dev/null ; sleep ${SLEEP}; done"; }
if (defined $S && $specificly eq 'builtin') { open LSOF, "lsof -n 2\>\
+&1 |" or die "couldnt execute lsof: $!\n"; close LSOF; $specificly = 
+"while true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2
+> /dev/null ; lsof -n | grep -v $$ | grep -v grep | grep -v lsof > /t
+mp/.custom.now.$magic 2> /dev/null ; diff /tmp/.custom.then.$magic /t
+mp/.custom.now.$magic | grep -E \"^$diffmethod\" 2> /dev/null ; sleep
+ ${SLEEP}; done"; }
if (defined $W && $specificly eq 'builtin') { open WHO, "who -a 2\>\&1
+ |" or die "couldnt execute who: $!\n"; close WHO; $specificly = "whi
+le true; do mv /tmp/.custom.now.$magic /tmp/.custom.then.$magic 2> /d
+ev/null ; who > /tmp/.custom.now.$magic 2> /dev/null ; diff /tmp/.cus
+tom.then.$magic /tmp/.custom.now.$magic | grep \"^$diffmethod\" 2> /d
+ev/null ; sleep ${SLEEP}; done"; }
printandorlog "# Opening: $specificly 2\>\&1\n";
open TD, "$specificly 2\>\&1 |" or die "cannot open $specificly becaus
+e of: $!\n";
printandorlog "# high-res legend: !=0.0-0.1 sec, @=0.1-0.2, #=0.2-0.3 
+... )=0.9-1 seconds\n";
printandorlog "# bulk-res legend: 0=.'s  1..9=1..9  10..35=a..z  >35=C
+  >40=D  >50=E  >60=F\n";
printandorlog "# " . showtime() . "ilf - input line frequency/time eve
+nt visualization (slf\@dreamscape.org)\n";
printandorlog "#(freq/time)";
#printandorlog "# input lines: ";
while(<TD>)
{
  # This will strip out all ANSI characters in your input.
  s/\e\[.*?m//go;
       
  # Store our previous time measurements.
  if (defined $timenow)    {    $oldtime = $timenow;    }
    
  # Take a time measurement.
  $timenow = time;
  $time = $timenow;
    
  # Determine if this is a ordinary line or one that is also a timecha
+nge & then act
  if (defined $time && defined $oldtime)    {
    # how much time has elapsed since the last input line?
    $diff = $time - $oldtime;
    # the sensitivity of this is currently fixed at 1 millisecond.
    if ($diff > 0.01)
    {
      # we dont care about 1.2345 etc...
      if ($diff > 1) { $diff = int($diff); }

      # reset the reallyfastlines counter whenever we do a timechange
      $pcount=0;

      # encode the timechange symbol (could be high resolution)
      $char=whatchar($diff);
            
      # allways reset before changing colors.
      print color 'reset';
      
      # our timechanges are generally allways supposed to be bold.
      print color 'bold';
      
      # change the color to our configured timechangecolor setting.
      print color "$timechangecolor";
      
      # increment the timechanges bean counter.
      $timechanges++;
    }
    else
    {
      $pcount++;
      $OLDdiff = $diff;
      $diff = $pcount;
      
      # encode the character to a symbol (could be high resolution)
      $char=whatchar($diff);
      
      # then begin coloring it.
      
      # allways reset before we add options.
      print color 'reset';
      
      # clean the spoon we will use to feed the options.
      $cmode = ""; ### (clean off the spoon)
      
      # determine if we should be blinking.
      if (/${blinkon}/o) { $blinkswitch = "ON"; }
      if (/${blinkoff}/o) { $blinkswitch = "OFF"; }
      if ($blinkswitch eq 'ON') { $cmode .= "blink "; }
      
      # determine if we should be reversing.
      if (/${reverseon}/o) { $reverseswitch = "ON"; }
      if (/${reverseoff}/o) { $reverseswitch = "OFF"; }
      if ($reverseswitch eq 'ON') { $cmode .= "reverse "; }
      
      # allways blink when we match this pattern
      $cmode .= "blink " if (/$whenblink/o);
      
      # allways reverse when we match this pattern
      $cmode .= "reverse " if (/$whenreverse/o);
      
      # allways bold when we match this pattern
      $cmode .= "bold " if (/$whenbold/o);
      
      # then finally add the color we'll be using.
      $cmode .= "$reallyfastcolor";
      
      # and then eat up! the colors! the colors! ;)
      print color "$cmode";
      
      $reallyfastlines++;
    }
  }
  
  $pnum++;
  
  # if ($char eq '.') { print color 'red'; }
  if ($lastchar eq $char) { $prun++; }
  if ($lastchar ne $char) { $prun=0; }
  
  # he's on fire!    override color decisions when we've seen way too 
+many packets within .1 second
  if ($prun > $hesonfire)  { print color 'reset'; print color "bold $h
+esonfirecolor"; $prun++; }
  if ($prun > ($hesonfire * 2) ) { print color 'reset'; print color "r
+everse blink bold $hesonfirecolor"; }
  #                                                        ^^^ go craz
+y if we're he's on fire 2x! ;)
  # (yes this could have been pnum, but what happens when you wrap lin
+es and are still on fire? ;))
  
  # Actually print the coded character
  printandorlog "$char";
  
  # Reset immediately for good measure (you never know when you might 
+control-C or lose link, eh?)
  print color 'reset';
  
  # To help determine when we're running at ludacris speed.
  $lastchar = "$char";
  
  # How many seconds have elapsed since the last gain on the clock?
  $secondssince = time - $timehere;
  
  $secondssince = $1 if ($secondssince =~ /^(\d+(?:|\.\ddd|\.\d\d|\.\d
+))/o);
  
  # If you want to add something special at the end of each line, make
+ it look like this.
  if ($pnum eq $max) { printandorlog " ${secondssince}s since" if (def
+ined $notthefirstlineplzthxu); }
  
  # when we have filled up your screen (maxxed out the setting in -m),
+ what happens on the next line?
  if ($pnum eq $max)
  {
    if (not defined $notthefirstlineplzthxu) { $notthefirstlineplzthxu
+=1 }
    printandorlog "\n";
    $nclock = showtime();
    if ($otime ne $nclock)
    {
      printandorlog "#\n";
      printandorlog "# Gain since last clockchange: ";
      $timehere = time;
      if (not defined $timechanges) { $timechanges="no" }
      printandorlog " \+${reallyfastlines} within .1s, ${timechanges} 
+timechange";
      if ($timechanges > 1 || $timechanges eq 0) { printandorlog "s"; 
+}
      printandorlog ".\n";
      $reallyfastlines=0;
      $timechanges=0;
    }
    printandorlog "# $nclock" if ($otime ne $nclock);
    printandorlog "# " if ($otime eq $nclock);
    printandorlog " " x 10 if ($otime eq $nclock);
    $otime = $nclock;
    $pnum=0;
  }
  ## $char = "." if ($char ne '.'); # normal printing character
  # normal printing character
  printandorlog " $_" if ($d);    
}
close TD;
printandorlog " The program finished..?\n";
exit;


sub strftime ($@)
{
  my ($format,$second,$minute,$hour,$day,$month,$year) = @_;
  my %convert = (
   Y => $year + 1900,
   m => sprintf( '%02d',$month + 1 ),
   d => sprintf( '%02d',$day ),
   H => sprintf( '%02d',$hour ),
   M => sprintf( '%02d',$minute ),
   S => sprintf( '%02d',$second ),
  );
  $format =~ s#%(.)#$convert{$1}#sg;
  return $format;
}

sub showtime
{
  my ($time2,$time,$hour,$min,$lclock,$clock,$pad,$extra);
  
  $time2 = strftime( '%H%M%S', localtime() );
  $time = $1 if ($time2 =~ /^(\d\d\d\d)\d\d/o);
  $hour = $1 if ($time =~ /^(\d\d)\d\d/o);
  $min = $1 if ($time =~ /^\d\d(\d\d)/o);
  if ($hour > 12) { $extra = "pm"; $hour -= 12; }
  else
  {
    if ($hour < 1) { $hour += 12; }
    $extra = "am";
  }
  
  $clock = "$hour:${min}$extra";     
  $lclock = length $clock;
  $pad = 10 - $lclock;
  $clock .= " " x $pad;
  return $clock;
}

sub whatchar
{
    my $diff = shift;  # pass a parameter rather than checking a globa
+l
    my $char;  # return this value rather than setting a global

    my @zeroto1 = qw/! @ # $ % ^ & * ( )/;  # characters for values <1
        # (the hash mark there will generate a warning, but it's okay)

    if ( $diff <= 0 ) {
        $char = ' ';  # differs from OP code
    }
    elsif ( $diff < 1 ) {
        $char = $zeroto1[int( $diff * 10 )];
    }
    elsif ( $diff < 10 ) {
        $char = ( $diff < 9 ) ? chr( int( $diff ) + ord( '1' )) : '0';
        # are you sure "234567890" is better than "123456789" ??
        # ... $char = chr( int( $diff ) + ord( '0' )) seems okay to me
    }
    elsif ( $diff <= 35 ) {
        $char = chr( int( $diff - 10 ) + ord( 'a' ));
    }
    else {
        $diff = 260 if ( $diff > 260 );
        $char = chr( int( $diff/10 ) - 3 + ord( 'C' ));
    }
    return $char;
}

#--------------------------------------------------------
#wishlist...
#  min..avg-range..max dynamic granular highlighting
#  choose-your-own-adventure legend writing
#--------------------------------------------------------
Replies are listed 'Best First'.
Re: ilf - input line frequency time event visualization
by graff (Chancellor) on Jul 13, 2005 at 04:36 UTC
    Lots of room for improvement here. First off, why do you abandon sensible line-breaks and indenting in those initial "if" blocks (just before the "while" loop)? It would be better if those were more legible. (And I'll bet it would be easier to find ways to eliminate some redundant coding there.)

    Second, why not use the perl-internal time and date functions (or one of the many modules for manipulating date/time values and strings), instead of relying on an OS-dependent "date" shell command? (Yes, the "date" command could have different default output formats on different versions of unix.)

    Third, that "whatchar" sub is kind of ugly and way too long. Here's how I would do it:

    sub whatchar { my $diff = shift; # pass a parameter rather than checking a globa +l my $char; # return this value rather than setting a global my @zeroto1 = qw/! @ # $ % ^ & * ( )/; # characters for values <1 # (the hash mark there will generate a warning, but it's okay) if ( $diff <= 0 ) { $char = ' '; # differs from OP code } elsif ( $diff < 1 ) { $char = $zeroto1[int( $diff * 10 )]; } elsif ( $diff < 10 ) { $char = ( $diff < 9 ) ? chr( int( $diff ) + ord( '1' )) : '0'; # are you sure "234567890" is better than "123456789" ?? # ... $char = chr( int( $diff ) + ord( '0' )) seems okay to me } elsif ( $diff <= 35 ) { $char = chr( int( $diff - 10 ) + ord( 'a' )); } else { $diff = 260 if ( $diff > 260 ); $char = chr( int( $diff/10 ) - 3 + ord( 'C' )); } return $char; }
    Note that in the OP code, a "$diff" value of zero had the effect of not changing the value of the global "$pchar". Was that intentional?

    Also, my version is written so that the caller doesn't need to do "int($diff)" before calling "whatchar()" (not that it matters, but it just makes more sense to me that way).

    Other things can be done to clean up and simplify your code -- I'm just hitting the points that leaped out at me.

    update: actually one more thing does jump out at me: fix the usage message; something like this:

    Usage: $0 'command line' $0 -- commmand [args ...] $0 builtin {-D|-N|-S|-W} [options ...] "builtin" functions: -D 'command line' : track "command" output -N [-n[o]] : track output of lsof (network status) ...
    Be a little less verbose and exhaustive in the examples, and more "schematic" and structured in the overview of args and options, to make it clear what the command line syntax is.
    A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://474423]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2024-03-19 08:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found