summaryrefslogtreecommitdiffstats
path: root/src/control.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/control.sh')
-rw-r--r--src/control.sh147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/control.sh b/src/control.sh
new file mode 100644
index 0000000..b25d00b
--- /dev/null
+++ b/src/control.sh
@@ -0,0 +1,147 @@
+# Functions for parsing control files.
+#
+# Copyright (C) 2012, 2013 Patrick "P. J." McDermott
+#
+# This file is part of the ProteanOS Development Kit.
+#
+# The ProteanOS Development Kit 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.
+#
+# The ProteanOS Development Kit 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 the ProteanOS Development Kit. If not, see
+# <http://www.gnu.org/licenses/>.
+
+control_file=
+control_line_nr=
+
+parse_control()
+{
+ local field_cb="${2}"
+ local paragraph_cb="${3}"
+ local req_fields="${4}"
+ local in_paragraph=
+ local line=
+ local para_req_fields=
+ local got_fields=
+ local name=
+ local value=
+
+ control_file="${1}"
+ control_line_nr=0
+
+ in_paragraph='false'
+
+ while IFS='' read -r line; do
+ control_line_nr=$(($control_line_nr + 1))
+ if [ "x$(echo ${line})" = 'x' ]; then
+ # Paragraph end.
+ if ${in_paragraph}; then
+ # The first line is blank to consolidate
+ # initialization code (see heredocument below).
+ in_paragraph='false'
+ if [ "x${name}" != 'x' ]; then
+ if ! "${field_cb}" "${name}" "${value}"
+ then
+ return 0
+ fi
+ fi
+ if ! "${paragraph_cb}"; then
+ return 0
+ fi
+ if [ "x${para_req_fields}" != 'x' ]; then
+ para_req_fields="$(printf "%s$(get_msg \
+ 'list_item_separator')" \
+ ${para_req_fields})"
+ parse_control_error \
+ 'control_missing_fields' \
+ "${para_req_fields}"
+ fi
+ fi
+ para_req_fields="$(printf '%s\n' ${req_fields})"
+ got_fields="${LF}"
+ name=''
+ value=''
+ elif [ "x${line#\#}" != "x${line}" ]; then
+ # Comment.
+ in_paragraph='true'
+ elif [ "x${line# }" = "x${line}" ]; then
+ # "Name: Value" line.
+ in_paragraph='true'
+ if [ "x${name}" != 'x' ]; then
+ if ! "${field_cb}" "${name}" "${value}"; then
+ return 0
+ fi
+ fi
+ name="${line%%:*}"
+ value="${line#*:}"
+ value="${value# }"
+ if [ "x${name}" = 'x' -o "x${name}" = "x${line}" ]; then
+ parse_control_error 'control_bad_nv'
+ continue
+ fi
+ if [ "x${para_req_fields}" != 'x' ]; then
+ # Remove field from list of required fields.
+ para_req_fields="$(printf '%s' "${para_req_fields}" | \
+ grep -Fv "${name}")"
+ fi
+ if [ "x${got_fields%${LF}${name}${LF}*}" != \
+ "x${got_fields}" ]; then
+ # Duplicate field.
+ parse_control_error 'control_duplicate_field' \
+ "${name}"
+ else
+ got_fields="${got_fields}${name}${LF}"
+ fi
+ else
+ # Continuation line.
+ in_paragraph='true'
+ if [ "x${name}" = 'x' ]; then
+ # Expecting a "Name: Value" line.
+ parse_control_error 'control_found_continuation'
+ continue
+ fi
+ value="${value}${LF}${line# }"
+ fi
+ done <<-EOF
+
+ $(cat "${control_file}")
+
+ EOF
+ # The first blank line above triggers the paragraph end code to
+ # consolidate initialization code.
+ # The second blank line above is needed because the command substitution
+ # removes any trailing newlines.
+
+ if [ "x${name}" != 'x' ]; then
+ if ! "${field_cb}" "${name}" "${value}"; then
+ return 0
+ fi
+ fi
+
+ return 0
+}
+
+parse_control_error()
+{
+ local msgid="${1}"
+ local file_info=
+ shift 1
+
+ if [ ${control_line_nr} -eq 0 ]; then
+ file_info="$(printf '%20s:' "${control_file}")"
+ else
+ file_info="$(printf '%20s(l%d):' "${control_file}" \
+ "${control_line_nr}")"
+ fi
+
+ warn "${file_info} $(get_msg "${msgid}")" "${@}"
+
+ return 0
+}