From 9c84a8b630df472bed071f548c51cff62b14d396 Mon Sep 17 00:00:00 2001
From: P. J. McDermott <pjm@nac.net>
Date: Fri, 29 Nov 2013 18:19:19 -0500
Subject: parse_control(): Support multiple paragraphs.

---
(limited to 'lib')

diff --git a/lib/control.sh b/lib/control.sh
index 51a7aef..9f76c67 100644
--- a/lib/control.sh
+++ b/lib/control.sh
@@ -29,11 +29,14 @@ control_line_nr=
 parse_control()
 {
 	local field_cb="${2}"
-	local req_fields="${3}"
-	local opt_fields="${4}"
+	local paragraph_cb="${3}"
+	local req_fields="${4}"
+	local opt_fields="${5}"
 	local all_fields=
-	local got_fields=
+	local in_paragraph=
 	local line=
+	local para_req_fields=
+	local got_fields=
 	local name=
 	local value=
 
@@ -43,17 +46,39 @@ parse_control()
 	req_fields="$(printf '%s\n' ${req_fields})"
 	opt_fields="$(printf '%s\n' ${opt_fields})"
 	all_fields="${LF}${req_fields}${LF}${opt_fields}${LF}"
-	got_fields="${LF}"
+
+	in_paragraph='false'
 
 	while IFS='' read -r line; do
 		control_line_nr=$(($control_line_nr + 1))
 		if [ "x$(echo ${line})" = 'x' ]; then
-			parse_control_error 'control_empty_line'
+			# Paragraph end.
+			if ${in_paragraph}; then
+				# The first line is blank to consolidate
+				# initialization code (see heredocument below).
+				in_paragraph='false'
+				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="${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
@@ -66,7 +91,7 @@ parse_control()
 				parse_control_error 'control_bad_nv'
 				continue
 			fi
-			if [ "x${req_fields}" != 'x' ]; then
+			if [ "x${para_req_fields}" != 'x' ]; then
 				if [ "x${all_fields%${LF}${name}${LF}*}" = \
 						"x${all_fields}" ]; then
 					# Unknown field.
@@ -76,8 +101,8 @@ parse_control()
 				else
 					# Remove field from list of required
 					# fields.
-					req_fields="$(printf '%s' \
-						"${req_fields}" | \
+					para_req_fields="$(printf '%s' \
+						"${para_req_fields}" | \
 						grep -Fv "${name}")"
 				fi
 			fi
@@ -91,6 +116,7 @@ parse_control()
 			fi
 		else
 			# Continuation line.
+			in_paragraph='true'
 			if [ "x${name}" = 'x' ]; then
 				# Expecting a "Name: Value" line.
 				parse_control_error 'control_found_continuation'
@@ -99,8 +125,14 @@ parse_control()
 			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
@@ -108,12 +140,6 @@ parse_control()
 		fi
 	fi
 
-	if [ "x${req_fields}" != 'x' ]; then
-		req_fields="$(printf "%s$(get_msg 'list_item_separator')" \
-			${req_fields})"
-		parse_control_error 'control_missing_fields' "${req_fields}"
-	fi
-
 	return 0
 }
 
--
cgit v0.9.1