1 # Perl module for sending queries to Sherlock search servers and parsing answers
3 # (c) 2002 Martin Mares <mj@ucw.cz>
5 # This software may be freely distributed and used according to the terms
6 # of the GNU Lesser General Public License.
8 package Sherlock::Query;
15 sub do_parse_tree($$$$);
20 my $server = shift @_;
33 my $sock = IO::Socket::INET->new(PeerAddr => $q->{SERVER}, Proto => 'tcp')
34 or return "900 Cannot connect to search server: $!";
35 print $sock $string, "\n";
39 $res =~ /^-(.*)/ and return $1;
40 $res =~ /^\+/ or return "901 Reply parse error";
51 if (!defined $block) {
53 push @{$q->{RAW}}, $block;
101 my ($q,$string) = @_;
103 # Send the query and gather results
104 if (my $err = $q->command($string)) { return $err; }
106 @$raw > 0 or return "902 Reply truncated";
108 # Split results to header, cards and footer
109 $q->{HEADER} = { RAW => shift @$raw };
110 $q->{FOOTER} = { RAW => [] };
111 if (@$raw && $raw->[@$raw-1]->[0] =~ /^\+/) {
112 $q->{FOOTER}{RAW} = pop @$raw;
115 while (my $r = shift @$raw) {
116 push @{$q->{CARDS}}, { RAW => $r };
120 parse_tree($q->{HEADER}, $hdr_syntax);
121 foreach my $c (@{$q->{CARDS}}) {
122 parse_tree($c, $card_syntax);
124 parse_tree($q->{FOOTER}, $footer_syntax);
132 my $syntax = shift @_;
133 do_parse_tree($tree->{RAW}, 0, $tree, $syntax);
136 sub do_parse_tree($$$$) {
139 my $cooked = shift @_;
140 my $syntax = shift @_;
143 $raw->[$i] =~ /^(.)(.*)/;
144 if (!defined($syntax->{$1}) && !defined($syntax->{''})) { return $i; }
145 if (ref $syntax->{$1} eq "ARRAY") {
146 push @{$cooked->{$1}}, $2;
148 } elsif (ref $syntax->{$1} eq "HASH") {
150 push @{$cooked->{$1}}, $block;
151 $i = do_parse_tree($raw, $i, $block, $syntax->{$1});
161 my $indent = shift @_;
163 if (ref $a eq "ARRAY") {
164 if (@{$a} == 0) { print "[]\n"; }
167 foreach my $k (@{$a}) {
169 print_tree($k, "$indent\t");
171 print $indent, "]\n";
175 foreach my $k (sort keys %{$a}) {
176 print "$indent\t$k => ";
177 print_tree($a->{$k}, "$indent\t");
179 print $indent, "}\n";
180 } elsif (defined $a) {