
# Utility function definitions for the various COIN scripts.

# Copyright (c) 2010 Lou Hafer	Simon Fraser University
# All Rights Reserved.
# This file is distributed under the Eclipse Public License.
# It is part of the BuildTools project in COIN-OR (www.coin-or.org)
#
# $Id$

# Functions to disassemble svn URLs and extract relevant bits, and utilities
# to find the best (most recent) stable and release URLs, calculate libtool
# version numbers, and compare URLs for compatibility based on major and minor
# version. Complicated because we have to account for trunk/stable/release and
# for the variant syntax of Data and ThirdParty URLs. For your normal project,
# it's
#   https://projects.coin-or.org/svn/ProjName/trunk
#   https://projects.coin-or.org/svn/ProjName/stable/M.m
#   https://projects.coin-or.org/svn/ProjName/releases/M.m.r
# with the proviso that sometimes it's
#   https://projects.coin-or.org/svn/ProjName/SubProj/trunk
# etc.
# For ThirdParty, it's just like a normal project, except the prefix string
# is longer:
#   https://projects.coin-or.org/svn/BuildTools/ThirdParty/ProjName
# Data is the real pain. Prior to 20101103 (1.0.x series), it had this form:
#  https://projects.coin-or.org/svn/Data/trunk/ProjName
#  https://projects.coin-or.org/svn/Data/stable/M.m/ProjName
#  https://projects.coin-or.org/svn/Data/releases/M.m.r/ProjName
# After 20101103 (1.1 and subsequent), it uses the same layout as ThirdParty,
# namely <svn prefix>/Data/Projname/<trunk, stable, releases>. Macros below
# will cope, but really you should be using pre-1.1 Data anyway.

# Extract the COIN base from the URL, up to svn. Just in case it ever changes.
# usage: baseURL=`extractBaseURL $svnURL`

extractBaseURL ()
{ 
  exbu_baseURL=`echo $1 | sed -n -e 's|\(.*/svn\)/.*$|\1|p'`
  echo "$exbu_baseURL"
}


# Extract branch type (trunk/stable/release) from the URL.
# usage: branchType=`extractTypeFromURL $svnURL`

extractTypeFromURL ()
{
  etfu_type="invalid"
  case "$1" in
    */trunk* ) etfu_type=trunk ;;
    */stable/* ) etfu_type=stable ;;
    */releases/* ) etfu_type=release ;;
  esac
  echo $etfu_type
}

# Determine if this is a `normal' URL, defined as not Data, ThirdParty, or
# BuildTools itself. ThirdParty lives in BuildTools as of 100628, so the
# condition is redundant. Returns yes or no.
# 101105 Exclude CoinBazaar, which follows the Data pattern. May not be the
#        correct choice if any CoinBazaar projects use BuildTools
# usage: isNormal=`isNormalURL $svnURL`

isNormalURL ()
{ case $1 in
    */BuildTools/* | */ThirdParty/* | */Data/* | */CoinBazaar/* )
       echo "no"
       ;;
    *) echo "yes"
       ;;
  esac
}

# Extract the project from a svn URL. The trick, for `normal' projects, is to
# handle CHiPPS, which has CHiPPS/Alps, Bcps, Blis. We can't assume the
# project name does not contain '/'. The heuristic is to look for everything
# between svn and one of trunk, stable, releases, or end of line.
# usage: projName=`extractProjFromURL $svnURL`

extractProjFromURL ()
{ 
  epfu_URL="$1"
  epfu_projPat='\([^/][^/]*\)'
  epfu_sfxPat='.*$'
  case "$epfu_URL" in
    */Data/trunk/* )
        epfu_pfxPat=svn/Data/trunk/
	;;
    */Data/stable/* | */Data/releases/* )
        epfu_pfxPat='svn/Data/[^/][^/]*/[0-9][0-9.]*/'
	;;
    */Data/* )
        epfu_pfxPat='svn/Data/'
	;;
    */ThirdParty/* )
        epfu_pfxPat=svn/BuildTools/ThirdParty/
	;;
    *)  epfu_type=`extractTypeFromURL $epfu_URL`
        epfu_pfxPat='svn/'
        epfu_projPat='\(.*\)'
        case $epfu_type in
	  trunk | stable | release )
	      epfu_sfxPat=$epfu_type'.*$'
	      ;;
	  * )
	      epfu_sfxPat='$'
	      ;;
	esac
	;;
  esac
  epfu_projName=`echo $epfu_URL | sed -n -e 's|.*/'$epfu_pfxPat$epfu_projPat$epfu_sfxPat'|\1|p'`
  epfu_projName=`echo $epfu_projName | sed -e 's|/$||'`
  echo "$epfu_projName"
}

# Extract the tail (directory) from a URL that specifies an external. Relevant
# only for normal projects, where the external will be a subdirectory
# of the project. Returns null for Data / ThirdParty / BuildTools.
# usage: projName=`extractTailFromExt $extURL`

extractTailFromExt ()
{ 
  etfe_tail=
  case "$1" in
    */Data/* )
	;;
    */BuildTools/ThirdParty/* )
	;;
    */BuildTools/* )
	;;
    */CoinBazaar/* )
        ;;
    *)
	etfe_pfxPat=
	case "$1" in
	  */trunk/* )
	      etfe_pfxPat='.*/trunk/'
	      ;;
	  */stable/* )
	      etfe_pfxPat='.*/stable/[0-9][0-9.]*/'
	      ;;
	  */releases/* )
	      etfe_pfxPat='.*/releases/[0-9][0-9.]*/'
	      ;;
	esac
	etfe_tail=`echo $1 | sed -n -e 's|'$etfe_pfxPat'\(.*\)|\1|p'`
	;;
  esac
  echo "$etfe_tail"
}


# CppAD uses a version string of the form YYYMMDD.rr. What a pain in the ass.
# Hence the scattered exceptions below.
# Extract the entire version string from a stable or release URL. Returns a
# null string if handed a trunk URL or if there's no version in the URL. The
# version number must have at least major.minor to match.
# usage: version=`extractVersionFromURL $svnURL`

extractVersionFromURL ()
{ 
  evfu_URL="$1"
  if expr "$evfu_URL" : '.*/stable/.*' >/dev/null 2>&1 ||
     expr "$evfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then
    if expr "$evfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
      evfu_verPat='\([0-9][0-9.]*\)'
    else
      evfu_verPat='\([0-9][0-9]*\.[0-9][0-9.]*\)'
    fi
    evfu_sfxPat='.*$'
    evfu_proj=`extractProjFromURL $evfu_URL`
    case "$evfu_URL" in
      */Data/stable/* | */Data/releases/* )
	  evfu_pfxPat='svn/Data/[^/][^/]*/'
	  ;;
      */ThirdParty/* )
	  evfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/'
	  ;;
      */Data/* )
	  evfu_pfxPat='svn/Data/'$evfu_proj'/[^/][^/]*/'
	  ;;
      *)
	  evfu_pfxPat='svn/'$evfu_proj'/[^/][^/]*/'
	  ;;
    esac
    evfu_verVer=`echo $1 | sed -n -e 's|.*/'$evfu_pfxPat$evfu_verPat$evfu_sfxPat'|\1|p'`
    echo "$evfu_verVer"
  else
    echo ""
  fi
}

# Replace the entire version string from a stable or release URL. A trunk
# URL will be unmodified. newRev will not be accessed unless the URL is a
# release. The version must have at least major.minor to match.
# usage: newURL=`replaceVersionInURL $oldURL $newMajor $newMinor $newRev`
# and just for CppAD,
# usage: newURL=`replaceVersionInURL $oldURL $newMajor $newRev`

replaceVersionInURL ()
{
  if expr "$1" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
    isCppAD=yes
  else
    isCppAD=no
  fi
  if test $isCppAD = no ; then
    rviu_verPat='[0-9][0-9]*\.[0-9][0-9.]*'
  else
    rviu_verPat='[0-9][0-9.]*'
  fi

  if expr "$1" : '.*/stable/.*' >/dev/null 2>&1 ; then
    if test $isCppAD = no ; then
      rviu_newVersion=$2.$3
    else
      rviu_newVersion=$2
    fi
  elif expr "$1" : '.*/releases/.*' >/dev/null 2>&1 ; then
    if test $isCppAD = no ; then
      rviu_newVersion=$2.$3.$4
    else
      rviu_newVersion=$2.$3
    fi
  else
    rviu_newVersion=
    rviu_newURL=$1
  fi
  if test -n "$rviu_newVersion" ; then
    rviu_newURL=`echo $1 | sed -n -e 's|^\(.*\)/'$rviu_verPat'\(.*\)$|\1/'$rviu_newVersion'\2|p'`
  fi
  echo $rviu_newURL
}

# Extract the major version number from a stable or release URL. Returns -1 if
# handed a trunk URL or if there's no version in the URL
# usage: majVer=`extractMajorFromURL $svnURL`

extractMajorFromURL ()
{ 
  ejfu_URL="$1"
  if expr "$ejfu_URL" : '.*/stable/.*' >/dev/null 2>&1 ||
     expr "$ejfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then
    ejfu_majPat='\([0-9][0-9]*\)'
    if expr "$ejfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
      ejfu_sfxPat='.*$'
    else
      ejfu_sfxPat='\.[0-9][0-9]*.*$'
    fi
    ejfu_proj=`extractProjFromURL $ejfu_URL`
    case "$ejfu_URL" in
      */Data/stable/* | */Data/releases/* )
	  ejfu_pfxPat='svn/Data/[^/][^/]*/'
	  ;;
      */ThirdParty/* )
	  ejfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/'
	  ;;
      */Data/* )
	  ejfu_pfxPat='svn/Data/'$ejfu_proj'/[^/][^/]*/'
	  ;;
      *)
	  ejfu_pfxPat='svn/'$ejfu_proj'/[^/][^/]*/'
	  ;;
    esac
    ejfu_majVer=`echo $ejfu_URL | sed -n -e 's|.*/'$ejfu_pfxPat$ejfu_majPat$ejfu_sfxPat'|\1|p'`
    echo "$ejfu_majVer"
  else
    echo "-1"
  fi
}

# Extract the minor version number from a stable or release URL. Returns -1 if
# handed a trunk URL or if there's no version in the URL.
# The CppAD form (YYYYMMDD.rr) doesn't have a minor version number.
# usage: minVer=`extractMinorFromURL $svnURL`

extractMinorFromURL ()
{ 
  emfu_URL="$1"
  if expr "$emfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
    echo "-1"
  elif expr "$emfu_URL" : '.*/stable/.*' >/dev/null 2>&1 ||
       expr "$emfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then
    emfu_minPat='[0-9][0-9]*\.\([0-9][0-9]*\)'
    emfu_sfxPat='.*$'
    emfu_proj=`extractProjFromURL $emfu_URL`
    case "$emfu_URL" in
      */Data/stable/* | */Data/releases/* )
	  emfu_pfxPat='svn/Data/[^/][^/]*/'
	  ;;
      */ThirdParty/* )
	  emfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/'
	  ;;
      */Data/* )
	  emfu_pfxPat='svn/Data/'$emfu_proj'/[^/][^/]*/'
	  ;;
      *)
	  emfu_pfxPat='svn/'$emfu_proj'/[^/][^/]*/'
	  ;;
    esac
    emfu_minVer=`echo $emfu_URL | sed -n -e 's|.*/'$emfu_pfxPat$emfu_minPat$emfu_sfxPat'|\1|p'`
    echo "$emfu_minVer"
  else
    echo "-1"
  fi
}

# Extract the release (revision) number from a release URL. Returns -1 if
# handed a trunk or stable URL
# usage: minVer=`extractReleaseFromURL $svnURL`

extractReleaseFromURL ()
{ 
  erfu_URL="$1"
  if expr "$erfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then
    if expr "$erfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
      erfu_relPat='[0-9][0-9]*\.\([0-9][0-9]*\)'
    else
      erfu_relPat='[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)'
    fi
    erfu_sfxPat='.*$'
    erfu_proj=`extractProjFromURL $erfu_URL`
    case "$erfu_URL" in
      */Data/releases/* )
	  erfu_pfxPat='svn/Data/[^/][^/]*/'
	  ;;
      */ThirdParty/* )
	  erfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/'
	  ;;
      */Data/*)
	  erfu_pfxPat='svn/Data/'$erfu_proj'/[^/][^/]*/'
	  ;;
      *)
	  erfu_pfxPat='svn/'$erfu_proj'/[^/][^/]*/'
	  ;;
    esac
    erfu_relVer=`echo $erfu_URL | sed -n -e 's|.*/'$erfu_pfxPat$erfu_relPat$erfu_sfxPat'|\1|p'`
    echo "$erfu_relVer"
  else
    echo "-1"
  fi
}

# Now some functions to locate the highest-numbered stable or release.

# Return the URL of the most recent stable branch matching the parameters.
# A value of -1 for major version is interpreted as `highest number'
# Returns an empty string if no suitable stable branch exists.
# usage: stableURL=`bestStable <URL> <major>`

bestStable ()
{ bstb_URL=$1
  bstb_majVer=$2

  # Construct a URL to send to the repository to list the stable branches.

  bstb_baseURL=`extractBaseURL $bstb_URL`
  bstb_proj=`extractProjFromURL $bstb_URL`

  case "$bstb_URL" in
    */Data/trunk/* )
	bstb_listURL=$bstb_baseURL/Data/stable
	;;
    */Data/* )
	bstb_listURL=$bstb_baseURL/Data/$bstb_proj/stable
	;;
    */ThirdParty/* )
	bstb_listURL=$bstb_baseURL/BuildTools/ThirdParty/$bstb_proj/stable
	;;
    * )
	bstb_listURL=$bstb_baseURL/$bstb_proj/stable
	;;
  esac

  bstb_rawls=`svn list $bstb_listURL | sort -nr -t. -k1,1 -k2,2`

  # echo "Raw ls: $bstb_rawls"

  # Filter the list of stable branches to remove any that do not match the
  # requested major version. Note that there's a / at the end of each URL.

  if test "$bstb_majVer" = "-1" ; then
    bstb_verPat='[0-9][0-9.]*/'
  elif expr "$bstb_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
    bstb_verPat=$bstb_majVer'/'
  else
    bstb_verPat=$bstb_majVer'\.[0-9][0-9]*'
  fi
  bstb_filter=
  for bstb_ver in $bstb_rawls ; do
    if  expr "$bstb_ver" : "$bstb_verPat" >/dev/null 2>&1 ; then
      bstb_filter="$bstb_filter $bstb_ver"
    fi
  done

  # echo "Filtered ls: $bstb_filter"

  # If there are any candidates left ...

  bstb_bestURL=
  if test -n "$bstb_filter" ; then

    # If we're dealing with old-style Data, we have to work a bit harder
    # to find our project. See if any of the filtered candidates contain
    # the correct project.

    case "$bstb_URL" in
      */Data/trunk/* | */Data/stable/* | */Data/releases/* )
        bstb_projPat='.*'$bstb_proj'/.*'
        # echo "Pattern: $bstb_projPat"
        for bstb_ver in $bstb_filter ; do
	  if  expr "$bstb_ver" : "$bstb_verPat" >/dev/null 2>&1 ; then
	    # echo "  url: $bstb_listURL/$bstb_ver"
	    bstb_svnls2="`svn list $bstb_listURL/$bstb_ver`"
	    # echo "  result: $bstb_svnls2"
	    if expr "$bstb_svnls2" : "$bstb_projPat" >/dev/null 2>&1 ; then
	      bstb_best=$bstb_ver
	      # echo "  best: $bstb_best"
	      break
	    fi
	  fi
        done
        bstb_bestURL=$bstb_listURL/$bstb_best$bstb_proj
      ;;
      *)
        bstb_bestURL=`echo $bstb_filter | sed -n -e 's|\([^/]*/\).*$|\1|p'`
        bstb_bestURL=$bstb_listURL/$bstb_bestURL
      ;;
    esac
  fi

  echo $bstb_bestURL
}

# Return the URL of the most recent release matching the parameters. Returns
# null if no suitable release exists.
# A value of -1 for major or minor version is interpreted as `highest number'
# A value of -1 for major version means that minor version is ignored.
# usage: releaseURL=`bestRelease <URL> <major> <minor>`

bestRelease ()
{ bstb_URL=$1
  bstb_majVer=$2
  bstb_minVer=$3

  # Construct a URL to send to the repository to list the releases.

  bstb_baseURL=`extractBaseURL $bstb_URL`
  bstb_proj=`extractProjFromURL $bstb_URL`

  case "$bstb_URL" in
    */Data/* )
	bstb_listURL=$bstb_baseURL/Data/$bstb_proj/releases
	;;
    */ThirdParty/* )
	bstb_listURL=$bstb_baseURL/BuildTools/ThirdParty/$bstb_proj/releases
	;;
    * )
	bstb_listURL=$bstb_baseURL/$bstb_proj/releases
	;;
  esac

  bstb_rawls=`svn list $bstb_listURL | sort -nr -t. -k1,1 -k2,2 -k3,3`

  # echo "Raw ls: $bstb_rawls"

  # Filter the list of releases to remove any that do not match the
  # requested major and minor version.

  if expr "$bstb_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
    isCppAD=yes
  else
    isCppAD=no
  fi

  if test "$bstb_majVer" = "-1" ; then
    bstb_verPat='[0-9][0-9.]*/'
  else
    bstb_verPat=$bstb_majVer
    if test $isCppAD = no &&
       test "$bstb_minVer" != "-1" ; then
      bstb_verPat="${bstb_verPat}\.$bstb_minVer"
    fi
    bstb_verPat="${bstb_verPat}"'\.[0-9][0-9]*/'
  fi

  # echo "Version pattern: $bstb_verPat"
  bstb_filter=
  for bstb_ver in $bstb_rawls ; do
    if  expr "$bstb_ver" : "$bstb_verPat" >/dev/null 2>&1 ; then
      bstb_filter="$bstb_filter $bstb_ver"
    fi
  done

  # echo "Filtered ls: $bstb_filter"

  # If there are any candidates left ...

  bstb_bestURL=
  if test -n "$bstb_filter" ; then

    # If we're dealing with old-style Data, we have to work a bit harder to find our
    # project. See if any of the filtered candidates contain the correct
    # project.

    case "$bstb_URL" in
      */Data/trunk/* | */Data/stable/* | */Data/releases/* )
        bstb_projPat='.*'$bstb_proj'/.*'
        # echo "Pattern: $bstb_projPat"
        for bstb_ver in $bstb_filter ; do
	  if  expr "$bstb_ver" : "$bstb_verPat" >/dev/null 2>&1 ; then
	    # echo "  url: $bstb_listURL/$bstb_ver"
	    bstb_svnls2="`svn list $bstb_listURL/$bstb_ver`"
	    # echo "  result: $bstb_svnls2"
	    if expr "$bstb_svnls2" : "$bstb_projPat" >/dev/null 2>&1 ; then
	      bstb_best=$bstb_ver
	      # echo "  best: $bstb_best"
	      break
	    fi
	  fi
        done
        bstb_bestURL=$bstb_listURL/$bstb_best$bstb_proj
      ;;
      *)
        bstb_bestURL=`echo $bstb_filter | sed -n -e 's|\([^/]*/\).*$|\1|p'`
        bstb_bestURL=$bstb_listURL/$bstb_bestURL
      ;;
    esac

  fi

  echo $bstb_bestURL
}

# Count the total number of stable branches for the project for the specified
# major version number, up to the specified minor version number (libtool age).
# Returns 0 if handed a trunk url, or if the url is BuildTools itself.
# usage: calcLibtoolAge <svnURL> <major> <minor>

calcLibtoolAge ()
{ cltc_URL=$1
  cltc_majVer=$2
  cltc_minVer=$3

  # Construct a URL to send to the repository to list the stable branches.

  cltc_baseURL=`extractBaseURL $cltc_URL`
  cltc_proj=`extractProjFromURL $cltc_URL`

  case "$cltc_URL" in
    */Data/* )
	cltc_listURL=$cltc_baseURL/Data/$cltc_proj/stable
	;;
    */ThirdParty/* )
	cltc_listURL=$cltc_baseURL/BuildTools/ThirdParty/$cltc_proj/stable
	;;
    */BuildTools/* )
	cltc_listURL=
	;;
    * )
	cltc_listURL=$cltc_baseURL/$cltc_proj/stable
	;;
  esac

  # Run an ls and filter for standard stable branches (M.m or YYYYMMDD)

  if test -n "$cltc_listURL" ; then
    cltc_rawls=`svn list $cltc_listURL | sed -n -e '/[0-9][0-9.]/p'`

    # echo "Raw ls: $cltc_rawls"

    # Filter the list of stable branches to remove any that do not match the
    # requested major version.

    if expr "$cltc_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then
      cltc_verPat=$cltc_majVer
    else
      cltc_verPat=$cltc_majVer'\.[0-9][0-9]*/'
    fi
    cltc_majfilter=
    for cltc_ver in $cltc_rawls ; do
      if  expr "$cltc_ver" : "$cltc_verPat" >/dev/null 2>&1 ; then
	cltc_majfilter="$cltc_majfilter $cltc_ver"
      fi
    done

    # echo "Filtered ls (major version): $cltc_majfilter"

    # For the specific major version, filter the list that matched on major
    # version to remove any that exceed the minor version.

    cltc_minfilter=
    for cltc_ver in $cltc_majfilter ; do
      cltc_min=`echo $cltc_ver | sed -e 's/[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/'`
      if expr $cltc_min '<=' $cltc_minVer >/dev/null 2>&1 ; then
	cltc_minfilter="$cltc_minfilter $cltc_ver"
      fi
    done

    # echo "Filtered ls (minor version): $cltc_minfilter"

    cltc_cnt=`echo $cltc_minfilter | wc -w | sed -e 's/ //g'`
  else
    cltc_cnt=0
  fi

  echo $cltc_cnt
}

# Count the total number of stable branches for the project up to the
# specified major.minor version number (libtool current).  Returns 0 if
# handed a trunk url, or if the url is BuildTools itself.
# usage: calcLibtoolCurrent <svnURL> <major> <minor>

calcLibtoolCurrent ()
{ cltc_URL=$1
  cltc_majVer=$2
  cltc_minVer=$3

  # Construct a URL to send to the repository to list the stable branches.

  cltc_baseURL=`extractBaseURL $cltc_URL`
  cltc_proj=`extractProjFromURL $cltc_URL`

  case "$cltc_URL" in
    */Data/* )
	cltc_listURL=$cltc_baseURL/Data/$cltc_proj/stable
	;;
    */ThirdParty/* )
	cltc_listURL=$cltc_baseURL/BuildTools/ThirdParty/$cltc_proj/stable
	;;
    */BuildTools/* )
	cltc_listURL=
	;;
    * )
	cltc_listURL=$cltc_baseURL/$cltc_proj/stable
	;;
  esac

  # Run an ls and filter for standard stable branches (M.m or YYYYMMDD)

  if test -n "$cltc_listURL" ; then
    cltc_rawls=`svn list $cltc_listURL | sed -n -e '/[0-9][0-9.]/p'`

    # echo "Raw ls: $cltc_rawls"

    # Filter the list of stable branches to find those with standard version
    # numbers.

    cltc_verPat='[0-9][0-9.]*/'

    cltc_stdfilter=
    for cltc_ver in $cltc_rawls ; do
      if  expr "$cltc_ver" : "$cltc_verPat" >/dev/null 2>&1 ; then
	cltc_stdfilter="$cltc_stdfilter $cltc_ver"
      fi
    done

    # echo "Filtered ls (standard): $cltc_stdfilter"

    # Filter to remove major versions that exceed the specified version.

    cltc_majfilter=
    for cltc_ver in $cltc_stdfilter ; do
      cltc_maj=`echo $cltc_ver | sed -e 's/\([0-9][0-9]*\)\.[0-9].*/\1/'`
      if expr $cltc_maj '<=' $cltc_majVer >/dev/null 2>&1 ; then
	cltc_majfilter="$cltc_majfilter $cltc_ver"
      fi
    done

    # echo "Filtered ls (major version): $cltc_majfilter"

    # For the specific major version, filter the list that matched on major
    # version to remove any that exceed the minor version.

    cltc_minfilter=
    cltc_verPat='s/'$cltc_majVer'\.\([0-9][0-9]*\).*/\1/'
    for cltc_ver in $cltc_majfilter ; do
      cltc_min=`echo $cltc_ver | sed -e $cltc_verPat`
      if test $cltc_min = $cltc_ver || \
              expr $cltc_min '<=' $cltc_minVer >/dev/null 2>&1 ; then
	cltc_minfilter="$cltc_minfilter $cltc_ver"
      fi
    done

    # echo "Filtered ls (minor version): $cltc_minfilter"

    cltc_cnt=`echo $cltc_minfilter | wc -w | sed -e 's/ //g'`
  else
    cltc_cnt=0
  fi

  echo $cltc_cnt
}


# Function to compare the versions in a pair of URLs for equality. The criteria
# is that the major and minor versions match. In theory, the release should
# not matter. Probably should be a parameter.
# usage: compareURLVersions <url1> <url2>

compareURLVersions ()
{
  url1_major=`extractMajorFromURL $1`
  url1_minor=`extractMinorFromURL $1`
  url2_major=`extractMajorFromURL $2`
  url2_minor=`extractMinorFromURL $2`

  if test $url1_major = $url2_major &&
     test $url1_minor = $url2_minor ; then
    echo "yes"
  else
    echo "no"
  fi
}

