aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-07-21 11:09:14 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-07-21 11:14:52 +0200
commited93f8450b92579dd639ae25361fa650613a5b7e (patch)
treec43b07d3d7723034fcbdbdf8e5ae805b6c361309 /libbutl
parent357172f4409c74d7a2ac963290fc70c7ae10e3b1 (diff)
Redo manifest parsing using bash co-process facility
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/buildfile5
-rw-r--r--libbutl/manifest-parser.bash13
-rw-r--r--libbutl/manifest-parser.bash.in83
-rw-r--r--libbutl/utility.bash.in14
4 files changed, 101 insertions, 14 deletions
diff --git a/libbutl/buildfile b/libbutl/buildfile
index 6509396..cd2643e 100644
--- a/libbutl/buildfile
+++ b/libbutl/buildfile
@@ -2,4 +2,7 @@
# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
# license : MIT; see accompanying LICENSE file
-./: bash{manifest-parser}
+./: bash{$path.base($path.base(*.bash.in))}
+
+bash{utility}: in{utility}
+bash{manifest-parser}: in{manifest-parser} bash{utility}
diff --git a/libbutl/manifest-parser.bash b/libbutl/manifest-parser.bash
deleted file mode 100644
index e726298..0000000
--- a/libbutl/manifest-parser.bash
+++ /dev/null
@@ -1,13 +0,0 @@
-# file : libbutl/manifest-parser.bash
-# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
-# license : MIT; see accompanying LICENSE file
-
-function butl_parse_manifest ()
-{
- printf ":1\0"
- printf "name:foo\0"
- printf "version:1.2.3\0"
- printf "description:foo\nexecutable\0"
- printf "depends:libfoo\0"
- printf "depends:libbar\0"
-}
diff --git a/libbutl/manifest-parser.bash.in b/libbutl/manifest-parser.bash.in
new file mode 100644
index 0000000..e40791e
--- /dev/null
+++ b/libbutl/manifest-parser.bash.in
@@ -0,0 +1,83 @@
+# file : libbutl/manifest-parser.bash.in
+# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+# license : MIT; see accompanying LICENSE file
+
+if [ "$butl_manifest_parser" = true ]; then
+ return 0
+else
+ butl_manifest_parser=true
+fi
+
+@import libbutl/utility@
+
+# Parse the manifest from stdin writing the binary representation to stdout.
+#
+# Normally you would use the start/finish functions below. But if you don't
+# care about errors, the following would be the typical usage:
+#
+# while IFS=: read -r -d '' n v; do
+# ...
+# done < <(butl_parse_manifest)
+#
+function butl_parse_manifest ()
+{
+ printf ":1\0"
+ printf "name:foo\0"
+ printf "version:1.2.3\0"
+ printf "description:foo\nexecutable\0"
+ printf "depends:libfoo\0"
+ printf "depends:libbar\0"
+}
+
+# Start the manifest parsing co-process setting the following "return"
+# variables:
+#
+# butl_manifest_parser_ofd
+# butl_manifest_parser_ifd
+# butl_manifest_parser_pid
+#
+# If <file> is not specified, then read from stdin.
+#
+# The typical usage:
+#
+# butl_manifest_parser_start
+#
+# while IFS=: read -ru "$butl_manifest_parser_ofd" -d '' n v; do
+# ...
+# done
+#
+# butl_manifest_parser_finish
+#
+function butl_manifest_parser_start () # [<file>]
+{
+ if [ "$#" -gt 0 ]; then
+ exec {butl_manifest_parser_ifd}<"$1"
+ else
+ exec {butl_manifest_parser_ifd}<&0
+ fi
+
+ # Note that bash co-process facility is racy: as soon as the process
+ # finishes, bash unsets COPROC/COPROC_PID (my guess would be it checks after
+ # each command in the script). This specific sequence of steps (and the one
+ # in *_finish()) seems to work reliably at least from bash 4.3.30 and
+ # up. See the following resources for details:
+ #
+ # http://wiki.bash-hackers.org/syntax/keywords/coproc
+ # http://tldp.org/LDP/abs/html/bashver4.html (coproc section)
+ # https://lists.gnu.org/archive/html/bug-bash/2014-02/msg00017.html
+ # https://lists.gnu.org/archive/html/bug-bash/2012-12/msg00069.html
+ # https://lists.gnu.org/archive/html/bug-bash/2012-10/msg00027.html
+ #
+ coproc { butl_parse_manifest; } <&"$butl_manifest_parser_ifd"
+ exec {butl_manifest_parser_ofd}<&"${COPROC[0]}"
+ butl_manifest_parser_pid="$COPROC_PID"
+}
+
+# Finish the manifest parsing co-process.
+#
+function butl_manifest_parser_finish ()
+{
+ exec {butl_manifest_parser_ofd}<&-
+ wait "$butl_manifest_parser_pid"
+ exec {butl_manifest_parser_ifd}<&-
+}
diff --git a/libbutl/utility.bash.in b/libbutl/utility.bash.in
new file mode 100644
index 0000000..bcc0f1b
--- /dev/null
+++ b/libbutl/utility.bash.in
@@ -0,0 +1,14 @@
+# file : libbutl/utility.bash.in
+# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+# license : MIT; see accompanying LICENSE file
+
+if [ "$butl_utility" = true ]; then
+ return 0
+else
+ butl_utility=true
+fi
+
+if (( BASH_VERSINFO[0] < 4 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 3 )); then
+ echo 'error: bash 4.3 or later is required' 2>&1
+ exit 1
+fi