#!/afs/athena/contrib/perl/perl
$RCS_ID = '$Id: row,v 2.1 1992/06/16 09:26:34 hobbs Exp $' ;
($pgm  = $0) =~ s-.*/-- ;
$HelpInfo = <<EOH ;

	    RDB operator: $pgm

Usage:  $pgm  [options]  [expression]

Options:
    -help    Print this help info.
    -fXXX    The expression is in the file 'XXX', instead of on the 
	     command line. The advantage in this case is that no quoting
	     of chars that might be special to the UNIX shell is necessary.

Selects rows from the input rdbtable that satisify an arbitrary expression
using column names.  Chars that are special to the UNIX shell must be quoted.

Comparsion operators may be of the form: gt, ge, lt, le, eq, ne.
E.g 'name eq Hobbs'.  Logical constructors 'or' and 'and' may be used; as
well as 'null' to indicate an empty data value.

All of the Comparsion operators and Logical constructors are reserved and
should not be used as column names (they are all lower case and four
chars or less).

This operator reads an rdbtable via STDIN and writes an rdbtable via STDOUT.
Options may be abbreviated.

$RCS_ID
EOH
%cmpop = ( "lt", "<", "le", "<=", "gt", ">", "ge", ">=", # cmp opers
	   "eq", "==", "ne", "!="  ) ;
%resw  = ( "or", "||", "and", "&&", "null", "\"\"" ) ;# reserved words
while ( $ARGV[0] =~ /^-/ ){				# Get args
    $_ = shift ;
    if( /-f(\S+)/ ){ $FEXP = $1 ; next ; }
    if( /-h.*/ ){ print $HelpInfo ; exit; }
    if( /-x.*/ ){ $XBUG++ ; next ; }
    die "Bad arg: $_\n", $HelpInfo ; exit ;
}
while(<STDIN>){
    print ;
    if( /^#\s|^\s+#/ && ! $lln ){		# comment 
	next ; }
    chop ;
    @F = split( /\t/, $_ );
    if( ++$lln == 1 ){				# col name line
	@H = @F ; # save headers
	next ; }
    if( $lln == 2 ){				# define line
	if( $FEXP ){			# exp from file
	    open( FEXP ) || die "Can't open input: $FEXP\n" ;
	    while( <FEXP> ){
		s/(^|\s+)#.*$// ;		# skip comments
		$x .= $_ ; }
	    @ARGV = split( ' ', $x ) ; }
	aa: for $arg ( @ARGV ){
	    for( $f=0 ; $f <= $#H ; $f++ ){
		if( $arg eq $H[$f] ){		# col name trans
		    $arg = '$F[' . $f . ']' ;
		    if( $F[$f] =~ /(\S+)/i && $1 =~ /N/i ){
			$numf++ ; } # num data flag, for next cycle
		    $poper = "COL" ;
		    next aa ; } }
	    if( $cmpop{$arg} ){			# cmp oper
		$poper = "CMP" ;# prev oper, for next cycle
		if( $numf ){ 	# numeric op trans
		    $numf = "" ;
		    $arg = $cmpop{$arg} ; }
		next aa ;  }
	    $numf = "" ;
	    if( $resw{$arg} ){			# reserved word 
		$arg = $resw{$arg} ;
		    $poper = "RES" ;
		next aa ; }
	    next aa if $poper ne 'CMP' ;
	    $poper = "VAL" ;			# data value, quote
	    $arg = '"' . $arg . '"' ;
	    next aa ;
	}
	$exp = join( ' ', @ARGV ) ;
	if( ! $exp ){ die "\nNo expression given.\n\n" ; }
	$prog = <<EOP ;
	while(<STDIN>){
	    chop ;
	    \@F = split( /\\t/, \$_ );
	    if( $exp ){
		print \$_, "\\n" ; }
	}
EOP
	last ;
    }
}
print STDERR $prog, "\n" if $XBUG ;
eval( $prog ) ;
print STDERR $@ if $@ ;
