From ed93f8450b92579dd639ae25361fa650613a5b7e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 21 Jul 2018 11:09:14 +0200 Subject: Redo manifest parsing using bash co-process facility --- libbutl/buildfile | 5 ++- libbutl/manifest-parser.bash | 13 ------- libbutl/manifest-parser.bash.in | 83 +++++++++++++++++++++++++++++++++++++++++ libbutl/utility.bash.in | 14 +++++++ 4 files changed, 101 insertions(+), 14 deletions(-) delete mode 100644 libbutl/manifest-parser.bash create mode 100644 libbutl/manifest-parser.bash.in create mode 100644 libbutl/utility.bash.in (limited to 'libbutl') 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 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 () # [] +{ + 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 -- cgit v1.1