RPM_MACRO_FILE=/usr/lib/rpm/macros

spec_query_with_macros () {
   local SPEC_FILE=$1; shift
   local BUILD_DIR=$1; shift
   local TIS_PATCH_VER=$1; shift
   local PBR_VERSION=$1; shift
   local rc

   TMPSPEC=$(mktemp /tmp/spec-utils-XXXXXX)
   cat $SPEC_FILE | sed 's/%(rpm.*)/%(echo 0)/' > $TMPSPEC

   rpmspec -P \
      --define="_tis_build_type ${BUILD_TYPE:-std}" \
      --define="_tis_dist .tis" \
      --define="tis_patch_ver ${TIS_PATCH_VER:-0}" \
      --define="pbr_version ${PBR_VERSION:-0}" \
      --define="platform_release ${PLATFORM_RELEASE:-00.00}" \
      --define="%_topdir $BUILD_DIR" \
      "${@}" \
      $TMPSPEC 2>> /dev/null
   rc=$?

   \rm -f $TMPSPEC
   return $rc
}

spec_evaluate () {
   local RAW_VALUE=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3

   local LAST_SPEC_EVALUATING="$SPEC_EVALUATING"
   local MACRO=""
   local MACRO_VALUE=""
   local RC=0

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   MACRO=$(expr match "$RAW_VALUE" '.*\(%{[^}]*}\)')
   if [ $? -ne 0 ]; then
      echo "$RAW_VALUE"
      return 0
   fi

   if [ "x$SPEC_EVALUATING" == "x" ]; then
       SPEC_EVALUATING=":$MACRO:"
   else
       echo "$SPEC_EVALUATING" | grep -q ":$MACRO:"
       if [ $? -eq 0 ]; then
           # Break a recursion
           >&2 echo "ERROR: evaluation of macro '$MACRO' failed due to recursion"
           return 1
       fi
       SPEC_EVALUATING="$LAST_SPEC_EVALUATING$MACRO:"
   fi

   # >&2 echo "spec_evaluate: MACRO=$MACRO"
   local MACRO_NAME2=${MACRO#%{}
   local MACRO_NAME3=${MACRO_NAME2%\}}
   local PREFIX=$(expr match "$MACRO_NAME3" '\([!?]*\)')
   local MACRO_NAME=${MACRO_NAME3#${PREFIX}}

   # >&2 echo "spec_evaluate: MACRO_NAME=$MACRO_NAME"
   MACRO_VALUE=$(spec_find_macro $MACRO_NAME $SPEC_FILE $RPMBUILD_DIR)
   if [ $? -ne 0 ]; then
      # >&2 echo "CALL: spec_find_global $MACRO_NAME $SPEC_FILE $RPMBUILD_DIR"
      MACRO_VALUE=$(spec_find_global $MACRO_NAME $SPEC_FILE $RPMBUILD_DIR)
      if [ $? -ne 0 ]; then
         MACRO_VALUE=$(spec_find_tag ${MACRO_NAME^} $SPEC_FILE $RPMBUILD_DIR)
         if [ $? -ne 0 ]; then
            MACRO_VALUE=$(macro_find_macro $MACRO_NAME $SPEC_FILE $RPMBUILD_DIR)
            if [ $? -ne 0 ]; then
               MACRO_VALUE=$(spec_find_macro_via_rpm $MACRO_NAME $SPEC_FILE $RPMBUILD_DIR)
               if [ $? -ne 0 ]; then
                  case "$MACRO_NAME" in
 
                     _tis_build_type)    MACRO_VALUE="${BUILD_TYPE}" ;;
                     _tis_dist)          MACRO_VALUE=".tis" ;;
                     tis_patch_ver)      MACRO_VALUE="{TIS_PATCH_VER:-0}" ;;
                     pbr_version)        MACRO_VALUE="{PBR_VERSION:-0}" ;;
                     platform_release)   MACRO_VALUE="$PLATFORM_RELEASE" ;;
                     _topdir)            MACRO_VALUE="$BUILD_DIR" ;;
                     *) ;;
                  esac

                  if [ "x$MACRO_VALUE" == "x" ]; then
                     if [ "$PREFIX" == '?' ]; then
                        >&2 echo "NOTE: optional macro '$MACRO' not defined"
                     else
                        >&2 echo "ERROR: evaluation of macro '$MACRO' failed"
                        SPEC_EVALUATING="$LAST_SPEC_EVALUATING"
                        return 1
                     fi
                  fi
               fi
            fi
         fi
      fi
   fi

   # >&2 echo "spec_evaluate: MACRO_VALUE=$MACRO_VALUE"
   local NEW_VALUE=${RAW_VALUE/"${MACRO}"/${MACRO_VALUE}}
   # >&2 echo "spec_evaluate: NEW_VALUE=$NEW_VALUE"
   spec_evaluate "$NEW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
   RC=$?
   SPEC_EVALUATING="$LAST_SPEC_EVALUATING"
   return $RC
}

macro_find_macro () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local LINE=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   # >&2 echo "grep ^%$TARGET $RPM_MACRO_FILE"
   LINE=$(grep "^%$TARGET[[:space:]]" $RPM_MACRO_FILE)
   if [ $? -eq 1 ]; then
       >&2 echo "macro_find_macro: '%$TARGET' not found in file '$RPM_MACRO_FILE'"
       echo ""
       return 1
   fi

   # >&2 echo "macro_find_macro: LINE=$LINE"
   local UNSTRIPED_VALUE=${LINE##"%$TARGET"}
   # >&2 echo "macro_find_macro: UNSTRIPED_VALUE=$UNSTRIPED_VALUE"
   local RAW_VALUE=${UNSTRIPED_VALUE//[[:space:]]/}
   # >&2 echo "macro_find_macro: RAW_VALUE=$RAW_VALUE"

   spec_evaluate "$RAW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
}

spec_find_macro_via_rpm () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3

   local RC=1

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   # >&2 echo "spec_find_macro_via_rpm: TARGET=$TARGET"

   case "$TARGET" in
      name|_name)       (spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{NAME}\n' | head -n 1 ; exit ${PIPESTATUS[0]} ); RC=$? ;;
      version|_version) (spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{VERSION}\n' | head -n 1 ; exit ${PIPESTATUS[0]} ); RC=$? ;;
      release|_release) (spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{RELEASE}\n' | head -n 1 ; exit ${PIPESTATUS[0]} ); RC=$? ;;
      *) ;;
   esac

   if [ $RC -ne 0 ]; then
      echo ""
   fi
   return $RC
}

spec_find_macro () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$2
   local LINE=""
   local UNSTRIPED_VALUE=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   # >&2 echo "grep ^%define $TARGET $SPEC_FILE"
   LINE=$(grep "^%define $TARGET[[:space:]]" $SPEC_FILE)
   if [ $? -eq 1 ]; then
       LINE=$(grep "^%$TARGET[[:space:]]" $SPEC_FILE)
       if [ $? -eq 1 ]; then
           >&2 echo "spec_find_macro: Neither '%define $TARGET' nor '%$TARGET' found in file '$SPEC_FILE'"
           echo ""
           return 1
       else
           UNSTRIPED_VALUE=${LINE##"%$TARGET"}
       fi
   else
       UNSTRIPED_VALUE=${LINE##"%define $TARGET"}
   fi

   # >&2 echo "spec_find_macro: LINE=$LINE"
   # >&2 echo "spec_find_macro: UNSTRIPED_VALUE=$UNSTRIPED_VALUE"
   local RAW_VALUE=$(echo ${UNSTRIPED_VALUE} | sed -e 's/^ *//g;s/ *$//g')
   # >&2 echo "spec_find_macro: RAW_VALUE=$RAW_VALUE"

   spec_evaluate "$RAW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
}

spec_find_tag () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local TIS_PATCH_VER=$4
   local PBR_VERSION=$5
   local LINE=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   local SPEC_FILE2=$(mktemp /tmp/tmp_spec_XXXXXX.spec)

   # Note: ${VAR:-val} is bash syntax for providing a default value.
   #       ie. if $VAR is not set, use 'val' as default value
   spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} > $SPEC_FILE2
   if [ $? != 0 ]; then
      #  spec_query_with_macros can fail on grub2 if it's just a spec file without SOURCES
      \cp $SPEC_FILE $SPEC_FILE2
   fi

   LINE=$(grep "^$TARGET:" $SPEC_FILE2 | head -n 1 ; exit ${PIPESTATUS[0]})
   if [ $? -eq 1 ]; then
       LINE=$(grep "^${TARGET^}:" $SPEC_FILE2 | head -n 1 ; exit ${PIPESTATUS[0]})
       if [ $? -eq 1 ]; then
           >&2 echo "spec_find_tag: '$TARGET:' not found in file '$SPEC_FILE'"
           echo ""
           \rm -f "$SPEC_FILE2"
           return 1
       else
           TARGET=${TARGET^}
       fi
   fi
   \rm -f "$SPEC_FILE2"

   # >&2 echo "spec_find_tag: LINE=$LINE"
   local UNSTRIPED_VALUE=${LINE##"$TARGET:"}
   # >&2 echo "spec_find_tag: UNSTRIPED_VALUE=$UNSTRIPED_VALUE"
   local RAW_VALUE=${UNSTRIPED_VALUE//[[:space:]]/}
   # >&2 echo "spec_find_tag: RAW_VALUE=$RAW_VALUE"

   spec_evaluate "$RAW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
}

spec_find_multi_tag () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$2
   local LINE=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   while read LINE; do
      # >&2 echo "spec_find_multi_tag: LINE=$LINE"
      local UNSTRIPED_VALUE=${LINE##"$TARGET:"}
      # >&2 echo "spec_find_multi_tag: UNSTRIPED_VALUE=$UNSTRIPED_VALUE"
      local RAW_VALUE=${UNSTRIPED_VALUE//[[:space:]]/}
      # >&2 echo "spec_find_multi_tag: RAW_VALUE=$RAW_VALUE"

      spec_evaluate "$RAW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
   done << EOF
$(grep "^$TARGET:" $SPEC_FILE)
EOF
}

spec_find_global () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local LINE=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   LINE=$(grep "^%global $TARGET" $SPEC_FILE)
   if [ $? -eq 1 ]; then
       >&2 echo "spec_find_global: '%global $TARGET' not found in file '$SPEC_FILE'"
       echo ""
       return 1
   fi

   # >&2 echo "spec_find_global: LINE=$LINE"
   local UNSTRIPED_VALUE=${LINE##"%global $TARGET"}
   # >&2 echo "spec_find_global: UNSTRIPED_VALUE=$UNSTRIPED_VALUE"
   local RAW_VALUE=${UNSTRIPED_VALUE//[[:space:]]/}
   # >&2 echo "spec_find_global: RAW_VALUE=$RAW_VALUE"

   spec_evaluate "$RAW_VALUE" "$SPEC_FILE" "$RPMBUILD_DIR"
}

spec_find_patch_args () {
   local PATCH_NO="$1"
   local SPEC_FILE="$2"
   local RPMBUILD_DIR="$3"

   local LINE=""
   local LINE2=""
   local PATCH_LOWER_NO

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   PATCH_LOWER_NO=$(echo $PATCH_NO | tr '[:upper:]' '[:lower:]')
   LINE=$(grep "^%$PATCH_LOWER_NO " $SPEC_FILE)
   if [ $? -eq 1 ]; then
       >&2 echo "pec_find_patch_args: $PATCH_LOWER_NO' not found in file '$SPEC_FILE'"
       echo "-p1"
       return 1
   fi
   LINE2=$(spec_evaluate "$LINE" "$SPEC_FILE" "$RPMBUILD_DIR")

   echo $LINE2 | cut -d' ' -f2- | sed 's/-b/-b -z/'
   return 0
}

spec_list_packages () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   local d=$(dirname $SPEC_FILE)
   local bd=$(basename $d)

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   if [ "$bd" == "SPECS" ]; then
       local dd=$(dirname $d)
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}\n' --define="%_topdir $dd" 2>> /dev/null 
   else
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}\n' 2>> /dev/null 
   fi

   if [ $? -ne 0 ]; then
      #  spec_query_with_macros can fail on grub2 if it's just a spec file without SOURCES
      local NAME=$(spec_find_tag Name "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      if [ $? -ne 0 ]; then
         >&2 echo "ERROR: failed to evaluate 'Name'"
         return 1
      fi
      echo $NAME
   
      grep "^%package" $SPEC_FILE | while read PACKAGE_LINE; do
          local PKG_NAME=""
          local PKG_NAME_RAW=$(echo $PACKAGE_LINE | awk '{ print $2 }')
          # >&2 echo "spec_list_packages: PKG_NAME_RAW=$PKG_NAME_RAW"
   
          local PKG_NAME_TEMP=""
          if [ "$PKG_NAME_RAW" == "-n" ]; then
              PKG_NAME_TEMP=$(echo $PACKAGE_LINE | awk '{ print $3 }')
          else
              PKG_NAME_TEMP="$NAME-$PKG_NAME_RAW"
          fi
          # >&2 echo "spec_list_packages: PKG_NAME_TEMP=$PKG_NAME_TEMP"
   
          PKG_NAME=$(spec_evaluate "$PKG_NAME_TEMP" "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
          if [ $? -ne 0 ]; then
              >&2 echo "ERROR: failed to evaluate package '$PACKAGE_LINE'"
              return 1
          fi
          # >&2 echo "spec_list_packages: PKG_NAME=$PKG_NAME"
   
          echo $PKG_NAME
      done
   fi
}

spec_list_versioned_packages () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   local d=$(dirname $SPEC_FILE)
   local bd=$(basename $d)

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   if [ "$bd" == "SPECS" ]; then
       local dd=$(dirname $d)
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}\n' --define="%_topdir $dd" 2>> /dev/null 
   else
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}\n' 2>> /dev/null 
   fi

   if [ $? -ne 0 ]; then
      #  spec_query_with_macros can fail on grub2 if it's just a spec file without SOURCES
      local NAME=$(spec_find_tag Name "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      if [ $? -ne 0 ]; then
         >&2 echo "ERROR: failed to evaluate 'Name'"
         return 1
      fi

      local VERSION=$(spec_find_tag Version "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      echo "$NAME-$VERSION"
   
      grep "^%package" $SPEC_FILE | while read PACKAGE_LINE; do
          local PKG_NAME=""
          local PKG_NAME_RAW=$(echo $PACKAGE_LINE | awk '{ print $2 }')
          # >&2 echo "spec_list_packages: PKG_NAME_RAW=$PKG_NAME_RAW"
   
          local PKG_NAME_TEMP=""
          if [ "$PKG_NAME_RAW" == "-n" ]; then
              PKG_NAME_TEMP=$(echo $PACKAGE_LINE | awk '{ print $3 }')
          else
              PKG_NAME_TEMP="$NAME-$PKG_NAME_RAW"
          fi
          # >&2 echo "spec_list_packages: PKG_NAME_TEMP=$PKG_NAME_TEMP"
   
          PKG_NAME=$(spec_evaluate "$PKG_NAME_TEMP" "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
          if [ $? -ne 0 ]; then
              >&2 echo "ERROR: failed to evaluate package '$PACKAGE_LINE'"
              return 1
          fi
          # >&2 echo "spec_list_packages: PKG_NAME=$PKG_NAME"
   
          echo "$PKG_NAME-$VERSION"
      done
   fi
}

spec_name_ver_rel () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   local NAME=""
   local d=$(dirname $SPEC_FILE)
   local bd=$(basename $d)

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   NAME=$(spec_find_tag Name $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
   VERSION=$(spec_find_tag Version $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
   RELEASE=$(spec_find_tag Release $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
   echo "$NAME-$VERSION-$RELEASE"
}

spec_list_ver_rel_packages () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   local d=$(dirname $SPEC_FILE)
   local bd=$(basename $d)

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   if [ "$bd" == "SPECS" ]; then
       local dd=$(dirname $d)
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}-%{release}\n' --define="%_topdir $dd" 2>> /dev/null 
   else
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}-%{release}\n' 2>> /dev/null 
   fi

   if [ $? -ne 0 ]; then
      #  spec_query_with_macros can fail on grub2 if it's just a spec file without SOURCES
      local NAME=$(spec_find_tag Name "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      if [ $? -ne 0 ]; then
         >&2 echo "ERROR: failed to evaluate 'Name'"
         return 1
      fi

      local VERSION=$(spec_find_tag Version "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      local RELEASE=$(spec_find_tag Release "$SPEC_FILE" $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0})
      echo "$NAME-$VERSION-$RELEASE"
   
      grep "^%package" $SPEC_FILE | while read PACKAGE_LINE; do
          local PKG_NAME=""
          local PKG_NAME_RAW=$(echo $PACKAGE_LINE | awk '{ print $2 }')
          # >&2 echo "spec_list_packages: PKG_NAME_RAW=$PKG_NAME_RAW"
   
          local PKG_NAME_TEMP=""
          if [ "$PKG_NAME_RAW" == "-n" ]; then
              PKG_NAME_TEMP=$(echo $PACKAGE_LINE | awk '{ print $3 }')
          else
              PKG_NAME_TEMP="$NAME-$PKG_NAME_RAW"
          fi
          # >&2 echo "spec_list_packages: PKG_NAME_TEMP=$PKG_NAME_TEMP"
   
          PKG_NAME=$(spec_evaluate "$PKG_NAME_TEMP" "$SPEC_FILE" $RPMBUILD_DIR)
          if [ $? -ne 0 ]; then
              >&2 echo "ERROR: failed to evaluate package '$PACKAGE_LINE'"
              return 1
          fi
          # >&2 echo "spec_list_packages: PKG_NAME=$PKG_NAME"
   
          echo "$PKG_NAME-$VERSION-$RELEASE"
      done
   fi
}

spec_list_ver_rel_arch_packages () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   local d=$(dirname $SPEC_FILE)
   local bd=$(basename $d)

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   if [ "$bd" == "SPECS" ]; then
       local dd=$(dirname $d)
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}-%{release}.%{arch}\n' --define="%_topdir $dd" 2>> /dev/null 
   else
       spec_query_with_macros $SPEC_FILE $RPMBUILD_DIR ${TIS_PATCH_VER:-0} ${PBR_VERSION:-0} -q --qf '%{name}-%{version}-%{release}.%{arch}\n' 2>> /dev/null 
   fi
}


spec_match_package_list () {
   local Aname=$1[@]
   local TARGET_LIST=("${!Aname}")
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local TARGET
   local PKG_NAME

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   for PKG_NAME in $(spec_list_packages "$SPEC_FILE" "$RPMBUILD_DIR"); do
       for TARGET in "${TARGET_LIST[@]}"; do
           if [ "$PKG_NAME" == "$TARGET" ]; then
               echo $TARGET
               return 0
           fi
           if [ $BUILD_TYPE == "rt" ] && [ "$PKG_NAME" == "${TARGET}-rt" ]; then
               echo $TARGET
               return 0
           fi
       done
   done

   return 1
}


spec_match_package () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local PKG_NAME

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   for PKG_NAME in $(spec_list_packages "$SPEC_FILE" "$RPMBUILD_DIR"); do
       if [ "$PKG_NAME" == "$TARGET" ]; then
           echo "found target '$TARGET' in file '$SPEC_FILE' as a package name"
           return 0
       fi
   done

   return 1
}

spec_match_target_list () {
   local Aname=$1[@]
   local TARGET_LIST=("${!Aname}")
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local TARGET
   local NAME
   local SERVICE
   local PKG_NAME

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   NAME=$(spec_find_tag Name "$SPEC_FILE" "$RPMBUILD_DIR")
   if [ $? -eq 0 ]; then
       for TARGET in "${TARGET_LIST[@]}"; do
           if [ "$NAME" == "$TARGET" ]; then
               echo $TARGET
               return 0
           fi
           if [ $BUILD_TYPE == "rt" ] && [ "$NAME" == "${TARGET}-rt" ]; then
               echo $TARGET
               return 0
           fi
       done
   fi

   SERVICE=$(spec_find_global service "$SPEC_FILE" "$RPMBUILD_DIR")
   if [ $? -eq 0 ]; then
       for TARGET in "${TARGET_LIST[@]}"; do
           if [ "$SERVICE" == "$TARGET" ]; then
               echo $TARGET
               return 0
           fi
           if [ $BUILD_TYPE == "rt" ] && [ "$SERVICE" == "${TARGET}-rt" ]; then
               echo $TARGET
               return 0
           fi
       done
   fi

   spec_match_package_list TARGET_LIST "$SPEC_FILE" "$RPMBUILD_DIR"
   if [ $? -eq 0 ]; then
       return 0
   fi

   return 1
}


spec_match_target () {
   local TARGET=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3
   local NAME
   local SERVICE
   local PKG_NAME

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   NAME=$(spec_find_tag Name "$SPEC_FILE" "$RPMBUILD_DIR")
   if [ $? -eq 0 ]; then
       if [ "$NAME" == "$TARGET" ]; then
           echo "found target '$TARGET' in file '$SPEC_FILE' as a name"
           return 0
       fi
   fi

   SERVICE=$(spec_find_global service "$SPEC_FILE" "$RPMBUILD_DIR")
   if [ $? -eq 0 ]; then
       if [ "$SERVICE" == "$TARGET" ]; then
           echo "found target '$TARGET' in file '$SPEC_FILE' as a service"
           return 0
       fi
   fi

   spec_match_package "$TARGET" "$SPEC_FILE" "$RPMBUILD_DIR"
   if [ $? -eq 0 ]; then
       return 0
   fi

   return 1
}


spec_build_requires () {
   local SPEC_FILE=$1
   local RPMBUILD_DIR=$2

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   spec_find_multi_tag BuildRequires $SPEC_FILE $RPMBUILD_DIR
}

spec_untar_path () {
   local SOURCE_NO=$1
   local SPEC_FILE=$2
   local RPMBUILD_DIR=$3

   >&2 echo "spec_untar_path SOURCE_NO=$SOURCE_NO SPEC_FILE=$SPEC_FILE"
   local UNTAR_PATH="."
   local AFTER=""

   if [ "x$RPMBUILD_DIR" == "x" ];then
      RPMBUILD_DIR=$(dirname $(dirname $SPEC_FILE))
   fi

   local SETUP=$(spec_find_macro setup $SPEC_FILE $RPMBUILD_DIR)
   AFTER=$(echo "$SETUP " | grep -o -e "[-]a[[:space:]]$SOURCE_NO[[:space:]]")
   if [ $? -eq 0 ]; then
      UNTAR_PATH=$(echo "$SETUP " | grep -o -e '[-]n[[:space:]][^[:space:]]*[[:space:]]' | awk '{ print $2}'; exit ${PIPESTATUS[1]})
      if [ $? -ne 0 ]; then
         NAME=$( spec_find_tag Name $SPEC_FILE $RPMBUILD_DIR)
         VERSION=$(spec_find_tag Version $SPEC_FILE $RPMBUILD_DIR)
         UNTAR_PATH="$NAME-$VERSION"
      fi
   fi
   echo "$UNTAR_PATH"
   return 0
}


spec_validate_tis_release () {
   local SPEC_FILE=$1

   if rpmspec --define='_tis_dist .tis' -P $SPEC_FILE 2>/dev/null | grep '^Version:' | grep '%{pbr_version}'; then
      return 0
   fi

   # TIS Release value must include either %{?_tis_dist}.%{tis_patch_ver} or %{tis_patch_ver}%{?_tis_dist}
   # Because spec_query_with_macros defines tis_patch_ver, we're using rpmspec directly here
   rpmspec --define='_tis_dist .tis' -P $SPEC_FILE 2>/dev/null | grep '^Release:' \
      | grep -qvE '\.tis\.%{tis_patch_ver}|%{tis_patch_ver}\.tis'
   if [ $? -eq 0 ]; then
      >&2 echo "ERROR: $SPEC_FILE: 'Release' must use %{?_tis_dist}.%{tis_patch_ver} or %{tis_patch_ver}%{?_tis_dist}"
      >&2 grep 'Release:' $SPEC_FILE
      return 1
   fi
   return 0
}