sh/dx and sh/dxcc now fully implemented
authordjk <djk>
Mon, 17 Aug 1998 00:34:39 +0000 (00:34 +0000)
committerdjk <djk>
Mon, 17 Aug 1998 00:34:39 +0000 (00:34 +0000)
abbreviated commands now work automagically
band data now implemented and working

cmd/show/dx.pl
cmd/show/dxcc.pl
perl/Bands.pm [new file with mode: 0644]
perl/DXCommandmode.pm
perl/DXM.pm
perl/DXUtil.pm
perl/Prefix.pm
perl/Spot.pm
perl/cluster.pl

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e3d3aed284a3fdd4431830e158314355c9acfd4e 100644 (file)
@@ -0,0 +1,116 @@
+#
+# show dx (normal)
+#
+# $Id$
+#
+
+my ($self, $line) = @_;
+my @list = split /\s+/, $line;               # split the line up
+
+my @out;
+my $f;
+my $call;
+my ($from, $to);
+my ($fromday, $today);
+my @freq;
+my @ans;
+my $pre;
+my $spotter;
+my $info;
+my $expr;
+
+while ($f = shift @list) {                 # next field
+  print "f: $f list: ", join(',', @list), "\n";
+  if (!$from && !$to) {
+    ($from, $to) = $f =~ /^(\d+)-(\d+)$/o;         # is it a from -> to count?
+    next if $from && $to > $from;
+  }
+  if (!$to) {
+    ($to) = $f =~ /^(\d+)$/o if !$to;              # is it a to count?
+    next if $to;
+  }
+  if (lc $f eq 'on' && $list[0]) {                  # is it freq range?
+    print "yup freq\n";
+    my @r = split '/', $list[0];
+       print "r0: $r[0] r1: $r[1]\n";
+       @freq = Bands::get_freq($r[0], $r[1]);
+       if (@freq) {                 # yup, get rid of extranous param
+         print "freq: ", join(',', @freq), "\n";
+         shift @list;
+         next;
+       }
+  }
+  if (lc $f eq 'day' && $list[0]) {
+    print "got day\n";
+    ($fromday, $today) = split '-', shift(@list);
+       next;
+  }
+  if (lc $f eq 'info' && $list[0]) {
+    print "got info\n";
+       $info = shift @list;
+       next;
+  }
+  if (lc $f eq 'spotter' && $list[0]) {
+    print "got spotter\n";
+       $spotter = uc shift @list;
+       next;
+  }
+  if (!$pre) {
+    $pre = uc $f;
+  }
+}
+
+# first deal with the prefix
+if ($pre) {
+  $expr = "\$f1 =~ /";
+  $pre =~ s|/|\\/|;          # change the slashes to \/ 
+  if ($pre =~ /^\*/o) {
+    $pre =~ s/^\*//;;
+    $expr .= "$pre\$/o";
+  } else {
+       $expr .= "^$pre/o";
+  }
+} else {
+  $expr = "1";             # match anything
+}
+  
+# now deal with any frequencies specified
+if (@freq) {
+  $expr .= ($expr) ? " && (" : "(";
+  my $i;
+  for ($i; $i < @freq; $i += 2) {
+    $expr .= "(\$f0 >= $freq[0] && \$f0 <= $freq[1]) ||";
+  }
+  chop $expr;
+  chop $expr;
+  $expr .= ")";
+}
+
+# any info
+if ($info) {
+  $expr .= " && " if $expr;
+  $info =~ s|/|\\/|;
+  $expr .= "\$f3 =~ /$info/io";
+}
+
+# any spotter
+if ($spotter) {
+  $expr .= " && " if $expr;
+  $spotter =~ s|/|\\/|;
+  $expr .= "\$f4 =~ /$spotter/o";
+}
+
+print "expr: $expr from: $from to: $to fromday: $fromday today: $today\n";
+  
+# now do the search
+my @res = Spot::search($expr, $fromday, $today, $from, $to);
+my $ref;
+my @dx;
+foreach $ref (@res) {
+  @dx = @$ref;
+  my $t = ztime($dx[2]);
+  my $d = cldate($dx[2]);
+  push @out, sprintf "%9s %-12s %s %s %-28s <%s>", $dx[0], $dx[1], $d, $t, $dx[3], $dx[4];
+}
+
+return (1, @out);
index f18eaef96646ccc5255b8f8d23c60d9b5747a9d6..b95bb7fec9e3b036af820d7f284fbb31d24b40cd 100644 (file)
@@ -5,23 +5,61 @@
 #
 
 my ($self, $line) = @_;
-my @list = split /\s+/, $line;               # generate a list of callsigns
+my @list = split /\s+/, $line;               # split the line up
 
-my $l;
 my @out;
+my $f;
+my $call;
+my ($from, $to);
+my ($fromday, $today);
+my @freq;
+my @ans;
 
-print "line: $line\n";
-foreach $l (@list) {
-  my @ans = Prefix::extract($l);
-  print "ans:", @ans, "\n";
-  next if !@ans;
+while ($f = shift @list) {                 # next field
+  print "f: $f list: ", join(',', @list), "\n";
+  if (!$from && !$to) {
+    ($from, $to) = $f =~ /^(\d+)-(\d+)$/o;         # is it a from -> to count?
+    next if $from && $to > $from;
+  }
+  if (!$to) {
+    ($to) = $f =~ /^(\d+)$/o if !$to;              # is it a to count?
+    next if $to;
+  }
+  if (lc $f eq 'on' && $list[0]) {                  # is it freq range?
+    print "yup freq\n";
+    my @r = split '/', $list[0];
+       print "r0: $r[0] r1: $r[1]\n";
+       @freq = Bands::get_freq($r[0], $r[1]);
+       if (@freq) {                 # yup, get rid of extranous param
+         print "freq: ", join(',', @freq), "\n";
+         shift @list;
+         next;
+       }
+  }
+  if (lc $f eq 'day' && $list[0]) {
+    print "got day\n";
+    ($fromday, $today) = split '-', $list[0];
+       shift @list;
+       next;
+  }
+  if (!@ans) {
+    @ans = Prefix::extract($f);                       # is it a callsign/prefix?
+  }
+}
+
+# no dxcc country, no answer!
+if (@ans) {                               # we have a valid prefix!
+  
+  # first deal with the prefix
   my $pre = shift @ans;
   my $a;
-  my $expr;
+  my $expr = "(";
   my $str = "Prefix: $pre";
   my $l = length $str;
+
+  # build up a search string for this dxcc country/countries
   foreach $a (@ans) {
-    $expr .= " || " if $expr;
+    $expr .= " || " if $expr ne "(";
        my $n = $a->dxcc();
     $expr .= "\$f5 == $n";
        my $name = $a->name();
@@ -29,9 +67,25 @@ foreach $l (@list) {
        push @out, $str;
        $str = pack "A$l", " ";
   }
+  $expr .= ")";
   push @out, $str;
-  print "expr: $expr\n";
-  my @res = Spot::search($expr);
+  
+  # now deal with any frequencies specified
+  if (@freq) {
+    $expr .= " && (";
+       my $i;
+       for ($i; $i < @freq; $i += 2) {
+         $expr .= "(\$f0 >= $freq[0] && \$f0 <= $freq[1]) ||";
+       }
+       chop $expr;
+       chop $expr;
+       $expr .= ")";
+  }
+
+  print "expr: $expr from: $from to: $to fromday: $fromday today: $today\n";
+  
+  # now do the search
+  my @res = Spot::search($expr, $fromday, $today, $from, $to);
   my $ref;
   my @dx;
   foreach $ref (@res) {
@@ -40,6 +94,8 @@ foreach $l (@list) {
        my $d = cldate($dx[2]);
        push @out, sprintf "%9s %-12s %s %s %-28s <%s>", $dx[0], $dx[1], $d, $t, $dx[3], $dx[4];
   }
+} else {
+  @out = DXM::msg('e4');
 }
 
 return (1, @out);
diff --git a/perl/Bands.pm b/perl/Bands.pm
new file mode 100644 (file)
index 0000000..9961269
--- /dev/null
@@ -0,0 +1,124 @@
+#
+# module to manage the band list
+#
+# Copyright (c) 1998 - Dirk Koopman G1TLH
+#
+# $Id$
+#
+
+package Bands;
+
+use DXUtil;
+use DXDebug;
+use DXVars;
+use Carp;
+
+use strict;
+use vars qw(%bands %regions $bandsfn %valid);
+
+%bands = ();   # the 'raw' band data
+%regions = ();  # list of regions for shortcuts eg vhf ssb
+$bandsfn = "$main::data/bands.pl";
+
+%valid = (
+  cw => '0,CW,parraypairs',
+  ssb => '0,SSB,parraypairs',
+  data => '0,DATA,parraypairs,parraypairs',
+  sstv => '0,SSTV,parraypairs',
+  fstv => '0,FSTV,parraypairs',
+  rtty => '0,RTTY,parraypairs',
+  pactor => '0,PACTOR,parraypairs',
+  packet => '0,PACKET,parraypairs',
+  repeater => '0,REPEATER,parraypairs',
+  fax => '0,FAX,parraypairs',
+  beacon => '0,BEACON,parraypairs',
+  band => '0,BAND,parraypairs',
+);
+
+# load the band data
+sub load
+{
+  %bands = ();
+  do $bandsfn;
+  confess $@ if $@;
+}
+
+# obtain a band object by callsign [$obj = Band::get($call)]
+sub get
+{
+  my $call = shift;
+  return $bands{$call};
+}
+
+# obtain all the band objects
+sub get_all
+{
+  return values(%bands);
+}
+
+# get all the band keys
+sub get_keys
+{
+  return keys(%bands);
+}
+
+# get all the frequency pairs associated with the band and sub-band offered
+# the band can be a region, sub-band can be missing
+# 
+# called Bands::get_freq(band-label, subband-label)
+sub get_freq
+{
+  my ($band, $subband) = @_;
+  my @band;
+  my $b;
+  my @out;
+  return () if !$band;
+  $subband = 'band' if !$subband;
+  
+  # first look in the region
+  $b = $regions{$band};
+  @band = @$b if $b;
+  @band = ($band) if @band == 0;
+  
+  # we now have a list of bands to scan for sub bands
+  foreach $b (@band) {
+    my $wb = $bands{$b};
+       if ($wb) {
+         my $sb = $wb->{$subband};
+         push @out, @$sb if $sb;
+       }
+  }
+  return @out;
+}
+
+#
+# return a list of valid elements 
+# 
+
+sub fields
+{
+  return keys(%valid);
+}
+
+#
+# return a prompt for a field
+#
+
+sub field_prompt
+{ 
+  my ($self, $ele) = @_;
+  return $valid{$ele};
+}
+
+no strict;
+sub AUTOLOAD
+{
+  my $self = shift;
+  my $name = $AUTOLOAD;
+  return if $name =~ /::DESTROY$/;
+  $name =~ s/.*:://o;
+  
+  @_ ? $self->{$name} = shift : $self->{$name} ;
+}
+
+1;
index 474d2c9c90d58ac1f8090ff3c75fd906650e8d90..9f7b3885712d7366a1daa66d4f272985502d528f 100644 (file)
@@ -16,13 +16,14 @@ use DXChannel;
 use DXUser;
 use DXVars;
 use DXDebug;
+use DXM;
+use Carp;
 
 use strict;
+use vars qw(%Cache %cmd_cache);
 
-#use vars qw( %Cache $last_dir_mtime @cmd);
-my %Cache = ();                  # cache of dynamically loaded routine's mod times
-my $last_dir_mtime = 0;          # the last time one of the cmd dirs was modified
-my @cmd = undef;                 # a list of commands+path pairs (in alphabetical order)
+%Cache = ();                  # cache of dynamically loaded routine's mod times
+%cmd_cache = ();            # cache of short names
 
 #
 # obtain a new connection this is derived from dxchannel
@@ -57,6 +58,7 @@ sub start
 
   # set some necessary flags on the user if they are connecting
   $self->{wwv} = $self->{talk} = $self->{ann} = $self->{here} = $self->{dx} = 1;
+  $self->prompt() if $self->{state} =~ /^prompt/o;
 
 }
 
@@ -68,7 +70,7 @@ sub normal
   my $self = shift;
   my $user = $self->{user};
   my $call = $self->{call};
-  my $cmdline = shift; 
+  my $cmdline = shift;
 
   # strip out //
   $cmdline =~ s|//|/|og;
@@ -77,12 +79,15 @@ sub normal
   my ($cmd, $args) = $cmdline =~ /^([\w\/]+)\s*(.*)/o;
 
   if ($cmd) {
-
+    
+       my ($path, $fcmd);
+   
     # first expand out the entry to a command
-    $cmd = search($cmd);
+    ($path, $fcmd) = search($main::localcmd, $cmd, "pl");
+    ($path, $fcmd) = search($main::cmd, $cmd, "pl") if !$path || !$fcmd;
 
-    my @ans = $self->eval_file($main::localcmd, $cmd, $args);
-       @ans = $self->eval_file($main::cmd, $cmd, $args) if !$ans[0];
+    my @ans = $self->eval_file($path, $fcmd, $args) if $path && $fcmd;
+#      @ans = $self->eval_file($main::cmd, $cmd, $args) if !$ans[0];
        if ($ans[0]) {
       shift @ans;
          $self->send(@ans) if @ans > 0;
@@ -178,10 +183,63 @@ sub get_all
 
 sub search
 {
-  my $short_cmd = shift;
-  return $short_cmd;    # just return it for now
+  my ($path, $short_cmd, $suffix) = @_;
+  my ($apath, $acmd);
+
+  # commands are lower case
+  $short_cmd = lc $short_cmd;
+  dbg('command', "command: $path $short_cmd\n");
+  
+  # return immediately if we have it
+  my ($apath, $acmd) = split ',', $cmd_cache{$short_cmd};
+  if ($apath && $acmd) {
+    dbg('command', "cached $short_cmd = ($apath, $acmd)\n");
+    return ($apath, $acmd) if $apath;
+  }
+  
+  # if not guess
+  my @parts = split '/', $short_cmd;
+  my $dirfn;
+  my $curdir = $path;
+  my $p;
+  my $i;
+  
+  for ($i = 0; $i < @parts; $i++) {
+    my  $p = $parts[$i];
+       opendir(D, $curdir) or confess "can't open $curdir $!";
+       my @ls = readdir D;
+       closedir D;
+       my $l;
+       foreach $l (sort @ls) {
+         next if $l =~ /^\./;
+      if ($i < $#parts) {            # we are dealing with directories
+        if ((-d "$curdir/$l") && $p eq substr($l, 0, length $p)) {
+                 dbg('command', "got dir: $curdir/$l\n");
+                 $dirfn .= "$l/";
+                 $curdir .= "/$l";
+                 last;
+               }
+      } else {                       # we are dealing with commands
+               next if !$l =~ /\.$suffix$/;       # only look for .$suffix files
+               if ($p eq substr($l, 0, length $p)) {
+                 $l =~ s/\.$suffix$//;      # remove the suffix
+                 chop $dirfn;               # remove trailing /
+                 $cmd_cache{"$short_cmd"} = join(',', ($path, "$dirfn/$l"));   # cache it
+          dbg('command', "got path: $path cmd: $dirfn/$l\n");
+                 return ($path, "$dirfn/$l"); 
+               }
+         }
+       }
+  }
+  return ();  
 }  
 
+# clear the command name cache
+sub clear_cmd_cache
+{
+  %cmd_cache = ();
+}
+
 #
 # the persistant execution of things from the command directories
 #
index 5c735fc7bf6190a89372cd1b435c8fe3532d20e7..e92f9f7a5aaeaf8ab300a7edf12508a14f111171 100644 (file)
@@ -31,6 +31,7 @@ require Exporter;
   e1 => 'Invalid command',
   e2 => 'Error: $_[0]',
   e3 => '$_[0]: $_[1] not found',
+  e4 => 'Need at least a prefix or callsign',
   email => 'E-mail address set to: $_[0]',
   heres => 'Here set on $_[0]',
   hereu => 'Here unset on $_[0]',
index c82705b7bb68507cb0725f69f7dafc03df5b08ef..605bfca4aa6bf23da413b96a1652bb2e4aeab7ce 100644 (file)
@@ -10,7 +10,7 @@ package DXUtil;
 
 require Exporter;
 @ISA = qw(Exporter);
-@EXPORT = qw(atime ztime cldate cldatetime slat slong yesno promptf
+@EXPORT = qw(atime ztime cldate cldatetime slat slong yesno promptf parray parraypairs
              print_all_fields 
             );
 
@@ -102,6 +102,29 @@ sub promptf
   return ($priv, $prompt);
 }
 
+# take an arg as an array list and print it
+sub parray
+{
+  return join(', ', @{shift});
+}
+
+# take the arg as an array reference and print as a list of pairs
+sub parraypairs
+{
+  my $ref = shift;
+  my $i;
+  my $out;
+  
+  for ($i = 0; $i < @$ref; $i += 2) {
+    my $r1 = @$ref[$i];
+       my $r2 = @$ref[$i+1];
+       $out .= "$r1-$r2, ";
+  }
+  chop $out;     # remove last space
+  chop $out;     # remove last comma
+  return $out;
+}
+
 # print all the fields for a record according to privilege
 #
 # The prompt record is of the format '<priv>,<prompt>[,<action>'
index d4ed48b33dbcf0fa7e8fd8e6daf9339c53cae900..b9e235cdd5ad7c6e01c7633139963dfff90505de 100644 (file)
@@ -16,9 +16,9 @@ use Data::Dumper;
 use strict;
 use vars qw($db  %prefix_loc %pre);
 
-local $db;     # the DB_File handle
-local %prefix_loc;   # the meat of the info
-local %pre;       # the prefix list
+$db;     # the DB_File handle
+%prefix_loc;   # the meat of the info
+%pre;       # the prefix list
 
 sub load
 {
index 167671ddab31f169db4edbbb0f90b1c53aec6a9a..64af363ee3045c718260e83f15a6f58e0a413275 100644 (file)
@@ -109,14 +109,9 @@ sub search
        $to = $defaultspots;
   }
 
-  $expr =~ s/\$f(\d)/zzzref->[$1]/g;               # swap the letter n for the correct field name
-  $expr =~ s/[\@\$\%\{\}]//g;                           # remove any other funny characters
-  $expr =~ s/\&\w+\(//g;                           # remove subroutine calls
-  $expr =~ s/eval//g;                              # remove eval words
-  $expr =~ s/zzzref/\$ref/g;                       # put back the $ref
-  $expr =~ s|(/.+/)|$1oi|g;                        # add oi characters to /ccc/
+  $expr =~ s/\$f(\d)/\$ref->[$1]/g;               # swap the letter n for the correct field name
   
-  print "expr=($expr), from=$from, to=$to\n";
+  dbg("search", "expr='$expr', spotno=$from-$to, day=$dayfrom-$dayto\n");
   
   # build up eval to execute
   $eval = qq(my \$c;
index 8a7ae01e7e02dd7368c3e027d4ac884a03b19737..e98dd156996eaafc1a175e26236c3b1e9501be3c 100755 (executable)
@@ -27,6 +27,7 @@ use DXProt;
 use DXCluster;
 use DXDebug;
 use Prefix;
+use Bands;
 
 package main;
 
@@ -161,12 +162,19 @@ foreach(@debug) {
 STDOUT->autoflush(1);
 
 # load Prefixes
+print "loading prefixes ...\n";
 Prefix::load();
 
+# load band data
+print "loading band data ...\n";
+Bands::load();
+
 # initialise User file system
+print "loading user file system ...\n"; 
 DXUser->init($userfn);
 
 # start listening for incoming messages/connects
+print "starting listener ...\n";
 Msg->new_server("$clusteraddr", $clusterport, \&login);
 
 # prime some signals
@@ -178,6 +186,7 @@ $SIG{'HUP'} = 'IGNORE';
 DXProt->init();
 
 # this, such as it is, is the main loop!
+print "orft we jolly well go ...\n";
 for (;;) {
   my $timenow;
   Msg->event_loop(1, 0.001);