#!/bin/sh

## epde -- EPD edit

## $Id: epdfilt,v 1.3 1999/12/18 20:19:22 heiner Exp $
## $Source: /home/heiner/ca/chest/EPD/RCS/epdfilt,v $

## FFS: add redundant data
##	pv --> pm
##	dm <--> ce

Usage="
Usage: $0 [options] [--] [file ...]
 -[h?]	 Print this.
 -m	 Print multiple lines per EPD (tab indented).
 -dm N	 Select only direct mates in N.
 -DM L H Select only direct mates between L and H.
 -prdm   Print just the dm value (direct mate).
 -o OPC  Restrict output to opcode OPC.  Multiple -o accumulate.
Filter for EPD data.
"

E_missarg='
    echo >&2 "$0: missing argument for \"$a\".  Try -h."
    exit 1
'

E_setOnly='
    optOnly=1
    optOlst="$optOlst ; Olst[\"${o}\"] = 1"
'

awk=awk
for a in nawk gawk awk ;do
    for d in /bin /usr/bin /usr/local/bin ;do
	t="$d/$a"
	if [ -f "$t" ] ;then
	    awk="$t"
	    #echo >&2 "$0: Using awk=$awk"
	    break 2
	fi
    done
done

optMulti=0
optDMmin=0
optDMmax=0
optDMpr=0
optOnly=0
optOlst=
while : ;do
    case $# in 0) break;;esac
    case $1 in -*);; *) break;;esac
    a="$1" ; shift
    case $a in
     --) break;;
     -[?h]) echo "$Usage" ; exit 0 ;;
     -m) optMulti=1 ;;
     -dm)   optDMmin="$1"
	    optDMmax="$1"
	    shift
	    ;;
     -DM)   optDMmin="$1"
	    optDMmax="$2"
	    shift 2
	    ;;
     -prdm) optDMpr=1 ;;
     -o)    case $# in 0) eval "$E_missarg" ;;esac
	    o=$1 ; shift
	    case $o in
	     *[!a-zA-Z_0-9]*)
		echo >&2 "$0: not acceptable char(s) in \"$o\"".
		exit 1
	    esac
	    eval "$E_setOnly"
	    ;;
     -omate)
	    o="bm" ; eval "$E_setOnly"
	    o="ce" ; eval "$E_setOnly"
	    o="dm" ; eval "$E_setOnly"
	    o="id" ; eval "$E_setOnly"
	    o="pv" ; eval "$E_setOnly"
	    ;;
     *) echo >&2 "$0: Unknown option '$a'.  Try '-h'."
	exit 1
    esac
done

cat ${1+"$@"} |
awk "
BEGIN {
    optMulti = ${optMulti}
    optDMmin = ${optDMmin}
    optDMmax = ${optDMmax}
    optDMpr  = ${optDMpr}
    optOnly  = ${optOnly} ${optOlst}
"'
    osep = (optMulti ? "\n\t" : " ")
    for( k in Olst ) printf("# Olst[\"%s\"] = %s\n", k, Olst[k])
}
/^[;%#]/	{ out(); print; next }
/^	/	{ if( fen != "" ) { appFields(1); next } }
{
    out()
    if( NF >= 4 ) {
	#fen = sprintf("%s %s %s %s", $1, $2, $3, $4)
	fen = $1 " " $2 " " $3 " " $4
	appFields(5)
    }
    next
}
END {
    out()
}
function out(  pr,dm,k,i)
{
    if( fen != "" ) {
	if( optDMpr ) {
	    printf("dm %4d\n", isDM())
	    pr = 0
	}else if( optDMmax > 0 ) {
	    dm = isDM()
	    pr = (dm && (optDMmin <= dm) && (dm <= optDMmax))
	}else {
	    pr = 1
	}
	if( pr ) {
	    mkSort()
	    # Print Line ...
	    printf("%s", fen)
	    for( i=1 ; i<=nop ; ++i ) {
		if( optOnly && ! (nam[x[i]] in Olst) ) continue
		printf("%s%s", osep, op[x[i]])
	    }
	    printf("\n")
	}
	# clean up ...
	fen = ""
	nop = 0
	#for( k in nam ) delete nam[k]
	#for( k in op  ) delete  op[k]
	#for( k in tok ) delete tok[k]
    }
}
function appFields(first  ,i,t,nt,s)
{
    for( i=first ; i<=NF ; ++i ) {
	nam[++nop] = $i
	s    = $i
	nt = 0
	while( (i<NF) && !match($i, ";$") ) {
	    t = $(++i)
	    s = s " " t
	    tok[nop,++nt] = t
	}
	op[nop]   = s
	ntok[nop] = nt
    }
}
function mkSort(  i,j,t,b,n)
{
    for( i=1 ; i<=nop ; ++i ) x[i] = i
    for( i=1 ; i<nop ; ++i ) {
	b = i; n=nam[x[i]]
	for( j=i+1 ; j<=nop ; ++j ) {
	    if( n > nam[x[j]] ) {
		n = nam[x[j]]; b=j
	    }
	}
	if( b != i ) {
	    t = x[i]; x[i] = x[b]; x[b] = t
	}
    }
}
function isDM(  ce,dm,p)
{
    if( fen == "" ) return 0
    ce = 0
    for( i=1 ; i<=nop ; ++i ) {
	if( nam[i] == "ce" ) {
	    ce = int(0 + tok[i,1])
	    if( ce > 32000 ) {
		p = 32767 - ce
		if( (p > 0) && (p % 2) ) return int((p+1)/2)
	    }else if( ce < -32000 ) {
		p = ce + 32767
		if( (p > 0) && !(p % 2) ) return - int(p/2)
	    }
	}
    }
    for( i=1 ; i<=nop ; ++i ) {
	if( nam[i] == "dm" ) {
	    dm = 0 + tok[i,1]
	    if( dm ) return dm
	}
    }
    for( i=1 ; i<=nop ; ++i ) {
	if( nam[i] == "pv" ) {
	    p = ntok[i]
	    if( (p > 0) && (p % 2) && match(tok[i,p], "#$") ) {
		return int((p+1)/2)
	    }
	}
    }
    ## FFS ce>600
    return 0
}
'
