#!/usr/bin/perl 
#  $HeadURL$ $LastChangedRevision$

($progname) = ($0 =~ /.*?([^\/]+)$/);
die "Usage: $progname <host-selector-expression>\n" if ($#ARGV+1 == 0);
$rocon_exp_string = join(' ', @ARGV);
@host_records = ();
    
#  Convert command line SQL expression to a perl expression reading a record $host_record.
#  '((' and '))' cause problems because split() will take them in one word, so 
#  we need to pad to avoid this.
$rocon_exp_string =~ s/(\(|\))/ $1 /g;
$rocon_exp_string =~ s/(^ *| *$| +(?= ))//g;
foreach $rocon_word (split(/ /, $rocon_exp_string)) {
    #  Keywords are replaced with lower case keywords (because 'NOT' etc are not understood by perl)
    if ((grep {lc($_) eq lc($rocon_word)} qw(\( \) and or not))) {
        $perl_word = lc($rocon_word);
    #  Integers and floats go through.
    } elsif ($rocon_word =~ /^\d+(?:|\.\d+)$/) {
        $perl_word = $rocon_word;
    #  Anything else is a variable to $-prefixed.
    } else {
        $perl_word = sprintf('defined(${$host_record}{memberships}{%s})', $rocon_word);
    }
    push(@perl_exp, $perl_word);
}
$perl_exp_string = join(' ', @perl_exp);

#  Check expression is valid.
#  %host_record is currently undefined, so ${$host_record}{memberships}{undef} is
#  also undefined, but defined(${$host_record}{memberships}{undef} ) *is* defined. 
#  This way we can test if the expression is valid. E.g. "defined(undef) and defined(undef)" 
#  is a valid expression but "defined(undef) and and defined(undef)" is not.
die("$rocon_exp_string: bad rocon expression\n") if (!defined(eval $perl_exp_string));

#  Import config data.
while (<STDIN>) {
    chomp;
    #  Ignore blank lines and comments (for SOFT-66)
    next if (/^\s*(#|$)/);
    ($host, $comma_separated_hostgroup_list) = (/^([^:]*):([^:]*)/);
    $host_record{host} = $host;
    #  Value is unimportant; it is whether it is defined or not that we test.
    $host_record{memberships}{$host} = 1;
    foreach $hostgroup (split(/,/, $comma_separated_hostgroup_list)) {
        #  Value is unimportant; it is whether it is defined or not that we test.
        $host_record{memberships}{$hostgroup} = 1;
    }
    push(@host_records, { %host_record });
    undef %host_record;
}

#  Find hosts for which the perl expression is true.
@matched_hosts = ();
foreach $host_record (@host_records) {
    push(@matched_hosts, ${$host_record}{host}) if (eval $perl_exp_string);
}

printf("%s\n", join("\n", @matched_hosts));
