# Functions for parsing dependency field values
#
# Copyright (C) 2012 Patrick McDermott
#
# This file is part of opkbuild.
#
# opkbuild is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# opkbuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with opkbuild. If not, see .
## @brief Parse a single package dependency string
## @details \fBob_parse_dep\fP() parses package dependencies in the format
## \fIpkg:archqual (rel ver) [arches] \fP, where the components
## \fI:archqual\fP, \fI(rel ver)\fP, \fI[arches]\fP, and \fI\fP
## are optional.
## @option -p pkg_var The name of the variable in which to store the
## package name.
## @option -q archqual_var The name of the variable in which to store the
## architecture qualifier, if any.
## @option -r rel_var The name of the variable in which to store the
## relationship operator, if any.
## @option -v ver_var The name of the variable in which to store the
## version, if any.
## @option -A arches_var The name of the variable in which to store the
## architectures, if any.
## @option -l plats_var The name of the variable in which to store the
## platforms, if any.
## @option -a host_arch The host architecture. If given, the dependency will
## only be printed on standard output if it applies to
## the given architecture.
## @option -P host_plat The host platform. If given, the dependency will
## only be printed on standard output if it applies to
## the given platform.
## @operand dep req The dependency to parse.
## @return Returns 0.
## @stdout Prints the dependency, with normalized formatting, if the dependency
## applies to the given host architecture and platform if any.
## @pure maybe This function has side effects when used with any of the options
## \fI-p\fP, \fI-q\fP, \fI-r\fP, \fI-v\fP, \fI-A\fP, or \fI-l\fP.
ob_parse_dep()
{
local opt=
local pkg_var=
local archqual_var=
local rel_var=
local ver_var=
local arches_var=
local plats_var=
local host_arch=
local host_plat=
local dep=
local dep_re=
local pkg=
local archqual=
local rel=
local ver=
local arches=
local plats=
local comp=
local comp_var=
OPTIND=1
while getopts 'p:q:r:v:A:l:a:P:' opt; do
case "${opt}" in
p)
pkg_var="${OPTARG}"
if ! _ob_validate_var_name "${pkg_var}"; then
return 125
fi
;;
q)
archqual_var="${OPTARG}"
if ! _ob_validate_var_name "${archqual_var}"; then
return 125
fi
;;
r)
rel_var="${OPTARG}"
if ! _ob_validate_var_name "${rel_var}"; then
return 125
fi
;;
v)
ver_var="${OPTARG}"
if ! _ob_validate_var_name "${ver_var}"; then
return 125
fi
;;
A)
arches_var="${OPTARG}"
if ! _ob_validate_var_name "${arches_var}"; then
return 125
fi
;;
l)
plats_var="${OPTARG}"
if ! _ob_validate_var_name "${plats_var}"; then
return 125
fi
;;
a)
host_arch="${OPTARG}"
;;
P)
host_plat="${OPTARG}"
;;
?)
return 125
;;
esac
done
shift $(($OPTIND - 1))
if [ ${#} -eq 1 ]; then
dep="${1}"
else
return 125
fi
# pkg[:archqual] [(rel ver)] [\[arches\]] []
dep_re='s/^ *([^ \(\[<]+) *(\((<<|<=|=|>=|>>) *(.+)\))?'
dep_re="${dep_re}"' *(\[(.+)\])? *(<(.+)>)? *$/\1\n\3\n\4\n\6\n\8/;'
# BusyBox sed supports -r and (as of version 1.22.0) -E.
dep="$(printf '%s\n' "${dep}" | sed -nr '
H;
${
g;
s/[\t\n]/ /g;
'"${dep_re}"'
p;
};
')"
{
IFS=':' read pkg archqual
read rel
read ver
read arches
read plats
} <<-EOF
${dep}
EOF
# Set the specified variables.
for comp in pkg archqual rel ver arches plats; do
comp_var="$(eval echo \"\$\{${comp}_var\}\")"
[ -z "${comp_var}" ] && continue
eval ${comp_var}=\"\$\{${comp}\}\"
done
if [ -n "${host_arch}" ] && ! ob_arch_is_concerned \
"${host_arch}" "${arches}"; then
return 0
fi
if [ -n "${host_plat}" ] && ! ob_plat_is_concerned \
"${host_plat}" "${plats}"; then
return 0
fi
printf '%s' "${pkg}"
[ -n "${archqual}" ] && printf ':%s' "${archqual}"
[ -n "${ver}" ] && printf ' (%s %s)' "${rel}" "${ver}"
[ -z "${host_arch}" -a -n "${arches}" ] && \
printf ' [%s]' "${arches}"
[ -z "${host_plat}" -a -n "${plats}" ] && \
printf ' [%s]' "${plats}"
printf '\n'
return 0
}
ob_reduce_deps()
{
local opt=
local host_arch=
local host_plat=
local deps=
local dep_and=
local dep_or=
local dep_list=
local dep_or_list=
local dep=
union='false'
OPTIND=1
while getopts 'a:P:u' opt; do
case "${opt}" in
a)
host_arch="${OPTARG}"
;;
P)
host_plat="${OPTARG}"
;;
u)
union='true'
;;
?)
return 125
;;
esac
done
shift $(($OPTIND - 1))
if [ ${#} -eq 1 ]; then
deps="${1}"
else
return 125
fi
IFS=','
for dep_and in ${deps}; do
unset IFS
if ! ${union}; then
IFS='|'
dep_or_list=
for dep_or in ${dep_and}; do
unset IFS
dep="$(ob_parse_dep -a "${host_arch}" \
-P "${host_plat}" "${dep_or}")"
if [ -n "${dep}" ]; then
if [ -n "${dep_or_list}" ]; then
dep_or_list="${dep_or_list} | "
fi
dep_or_list="${dep_or_list}${dep}"
fi
done
unset IFS
if [ -n "${dep_or_list}" ]; then
if [ -n "${dep_list}" ]; then
dep_list="${dep_list}, "
fi
dep_list="${dep_list}${dep_or_list}"
fi
else
dep="$(ob_parse_dep -a "${host_arch}" \
-P "${host_plat}" "${dep_and}")"
if [ -n "${dep}" ]; then
if [ -n "${dep_list}" ]; then
dep_list="${dep_list}, "
fi
dep_list="${dep_list}${dep}"
fi
fi
done
unset IFS
echo "${dep_list}"
return 0
}