+ my @f = split /\s+/, $line;
+ my $conj = ' && ';
+ my $not = "";
+ while (@f) {
+ if ($ntoken == 0) {
+
+ if (@f && $dxchan->priv >= 8 && ((is_callsign(uc $f[0]) && DXUser->get(uc $f[0])) || $f[0] =~ /(?:node|user)_default/)) {
+ $call = shift @f;
+ if ($f[0] eq 'input') {
+ shift @f;
+ $flag++;
+ }
+ } else {
+ $call = $dxchan->call;
+ }
+
+ if (@f && $f[0] =~ /^\d$/) {
+ $fno = shift @f;
+ }
+
+ $filter = Filter::read_in($sort, $call, $flag);
+ $filter = Filter->new($sort, $call, $flag) if !$filter || $filter->isa('Filter::Old');
+
+ $ntoken++;
+ next;
+ }
+
+ # do the rest of the filter tokens
+ if (@f) {
+ my $tok = shift @f;
+ if ($tok eq '(') {
+ if ($s) {
+ $s .= $conj;
+ $user .= $conj;
+ $conj = "";
+ }
+ if ($not) {
+ $s .= $not;
+ $user .= $not;
+ $not = "";
+ }
+ $s .= $tok;
+ $user .= $tok;
+ next;
+ } elsif ($tok eq ')') {
+ $conj = ' && ';
+ $not ="";
+ $s .= $tok;
+ $user .= $tok;
+ next;
+ } elsif ($tok eq 'all') {
+ $s .= '1';
+ $user .= $tok;
+ last;
+ } elsif ($tok eq 'or') {
+ $conj = ' || ' if $conj ne ' || ';
+ next;
+ } elsif ($tok eq 'and') {
+ $conj = ' && ' if $conj ne ' && ';
+ next;
+ } elsif ($tok eq 'not' || $tok eq '!') {
+ $not = '!';
+ next;
+ }
+ if (@f) {
+ my $val = shift @f;
+ my @val = split /,/, $val;
+
+ if ($s) {
+ $s .= $conj ;
+ $user .= $conj;
+ $conj = ' && ';
+ }
+
+ if ($not) {
+ $s .= $not;
+ $user .= $not;
+ $not = '';
+ }
+
+ $user .= "$tok $val";
+
+ my $fref;
+ my $found;
+ foreach $fref (@$self) {
+
+ if ($fref->[0] eq $tok) {
+ if ($fref->[4]) {
+ my @nval;
+ for (@val) {
+ push @nval, split(',', &{$fref->[4]}($dxchan, $_));
+ }
+ @val = @nval;
+ }
+ if ($fref->[1] eq 'a') {
+ my @t;
+ for (@val) {
+ s/\*//g;
+ push @t, "\$r->[$fref->[2]]=~/$_/i";
+ }
+ $s .= "(" . join(' || ', @t) . ")";
+ } elsif ($fref->[1] eq 'c') {
+ my @t;
+ for (@val) {
+ s/\*//g;
+ push @t, "\$r->[$fref->[2]]=~/^\U$_/";
+ }
+ $s .= "(" . join(' || ', @t) . ")";
+ } elsif ($fref->[1] eq 'n') {
+ my @t;
+ for (@val) {
+ return ('num', $dxchan->msg('e21', $_)) unless /^\d+$/;
+ push @t, "\$r->[$fref->[2]]==$_";
+ }
+ $s .= "(" . join(' || ', @t) . ")";
+ } elsif ($fref->[1] =~ /^n[ciz]$/ ) { # for DXCC, ITU, CQ Zone
+ my $cmd = $fref->[1];
+ my @pre = Prefix::to_ciz($cmd, @val);
+ return ('numpre', $dxchan->msg('e27', $_)) unless @pre;
+ $s .= "(" . join(' || ', map {"\$r->[$fref->[2]]==$_"} @pre) . ")";
+ } elsif ($fref->[1] =~ /^ns$/ ) { # for DXCC, ITU, CQ Zone
+ my $cmd = $fref->[1];
+ my @pre = Prefix::to_ciz($cmd, @val);
+ return ('numpre', $dxchan->msg('e27', $_)) unless @pre;
+ $s .= "(" . "!\$USDB::present || grep \$r->[$fref->[2]] eq \$_, qw(" . join(' ' ,map {uc} @pre) . "))";
+ } elsif ($fref->[1] eq 'r') {
+ my @t;
+ for (@val) {
+ return ('range', $dxchan->msg('e23', $_)) unless /^(\d+)\/(\d+)$/;
+ push @t, "(\$r->[$fref->[2]]>=$1 && \$r->[$fref->[2]]<=$2)";
+ }
+ $s .= "(" . join(' || ', @t) . ")";
+ } elsif ($fref->[1] eq 't') {
+ my @t;
+ for (@val) {
+ s/\*//g;
+ push @t, "\$r->[$fref->[2]]=~/$_/i";
+ }
+ $s .= "(" . join(' || ', @t) . ")";
+ } else {
+ confess("invalid letter $fref->[1]");
+ }
+ ++$found;
+ last;
+ }
+ }
+ return ('unknown', $dxchan->msg('e20', $tok)) unless $found;
+ } else {
+ return ('no', $dxchan->msg('filter2', $tok));
+ }
+ }
+