#!/bin/bash

# This program preprocesses #if's of the form:
# #if LINUX_VERSION_CODE > KERNEL_VERSION ( ?, ?, ??)
# #if LINUX_VERSION_CODE < KERNEL_VERSION ( ?, ?, ??)
#
# To be used to clean up code before submission to the kernel.
#
# - Joe Thornber

# Return +1 if $k > $v
# Return  0 if $k = $v
# Return -1 if $k < $v
function cmp_kver {
    local kv=$1
    shift
    local vv=$1
    shift

    if [ -z "$kv" -o -z "$vv" ]; then
    	return 0;
    fi

    local k1=`echo $kv | sed -e "s/\([0-9][0-9]*\)\..*/\1/"`
    local k2=`echo $kv | sed -e "s/[^.]*\.\([0-9][0-9]*\)\..*/\1/"`
    local k3=`echo $kv | sed -e "s/[^.]*\.[^.]*\.\([0-9][0-9]*\)/\1/"`
   
    local v1=`echo $vv | sed -e "s/\([0-9][0-9]*\)\..*/\1/"`
    local v2=`echo $vv | sed -e "s/[^.]*\.\([0-9][0-9]*\)\..*/\1/"`
    local v3=`echo $vv | sed -e "s/[^.]*\.[^.]*\.\([0-9][0-9]*\)/\1/"`

    #echo "$k1 $k2 $k3";
    #echo "$v1 $v2 $v3";
    if [ $v1 -lt $k1 ]; then return 1; fi
    if [ $v1 -gt $k1 ]; then return -1; fi
    if [ $v2 -lt $k2 ]; then return 1; fi
    if [ $v2 -gt $k2 ]; then return -1; fi
    if [ $v3 -lt $k3 ]; then return 1; fi
    if [ $v3 -gt $k3 ]; then return -1; fi
    return 0;
}


kver=$1
shift

if [ -z "$kver" ]; then
	echo "Usage: select_version [kernel_version]"
	exit 1;
fi

if [ `echo $kver | \
	sed -e "/\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)/d"` ];
then
	echo "Please give kernel version in form #.#.## eg., 2.4.12"
	exit 2;
fi
k1=`echo $kver | sed -e "s|([0-9]+)\.([0-9]+)\.([0-9]+)/)|\1|"`;
k2=`echo $kver | sed -e "s|([0-9]+)\.([0-9]+)\.([0-9]+)/)|\2|"`;
k3=`echo $kver | sed -e "s|([0-9]+)\.([0-9]+)\.([0-9]+)/)|\3|"`;

declare -a in_section;
declare -a choose_section;
depth=0;

while [ read input ]; do
    if [ -z `echo $input | sed -e "/[[:blank:]]*\#[[:blank:]]*if/d"` ]; then
	depth=$(($depth+1)); 
	if [ -z `echo $input | sed -e "/[[:blank:]]*\#[[:blank:]]*if[[:blank:]][[:blank:]]*LINUX_VERSION_CODE[[:blank:]][[:blank:]]((<)|(>)|(>=)|(<=)|(==))[[:blank:]][[:blank:]]KERNEL_VERSION[[:blank:]]*\([[:blank:]]*([0-9][0-9]*)[[:blank:]]*,[[:blank:]]*([0-9][0-9]*)[[:blank:]]*,[[:blank:]]*([0-9][0-9])/x)" ]; then 
	    next if(scalar(@in_section) && !$choose_section[$#choose_section]);
	    push @in_section, $depth;

	    $cmp = &cmp_kver($7, $8, $9);
	    $choose = 0;
  	    if [ $1 eq '<' -a $cmp == -1 ]; then $choose = 1; fi
  	    if($1 eq '>' && $cmp == 1) {$choose = 1;}
  	    if($1 eq '==' && $cmp == 0) {$choose = 1;}
  	    if($1 eq '<=' && ($cmp == -1 || $cmp == 0)) {$choose = 1;}
  	    if($1 eq '>=' && ($cmp == 1 || $cmp == 0)) {$choose = 1;}

	    push @choose_section, $choose;
	    next;
	}
    else 
    	if(/\s*\#\s*else/); then
		if(scalar(@in_section) &&
		   ($depth == $in_section[$#in_section])) {
		    $choose_section[$#choose_section] =
			!$choose_section[$#choose_section];
		    next;
	
    	else;
		if(/\s*\#\s*endif/) {
			$depth--;
			if(scalar(@in_section) &&
			   ($depth < $in_section[$#in_section])) {
			    pop @in_section;
			    pop @choose_section;
			    next;
			endif
		endif
	endif
    endif
    print if(!scalar(@in_section) || $choose_section[$#choose_section]);
}

sub cmp_kver {
    ($v1, $v2, $v3) = @_;
    if($v1 < $k1) {return 1;}
    if($v1 > $k1) {return -1;}
    if($v2 < $k2) {return 1;}
    if($v2 > $k2) {return -1;}
    if($v3 < $k3) {return 1;}
    if($v3 > $k3) {return -1;}
    return 0;
}
