]> Lady’s Gitweb - Shushe/commitdiff
Improve xargs handling
authorLady <redacted>
Thu, 2 May 2024 05:48:21 +0000 (01:48 -0400)
committerLady <redacted>
Thu, 2 May 2024 06:15:21 +0000 (02:15 -0400)
- Always specify -E '' to disable end‐of‐file handling

- Quote standard input before passing it thru to xargs, and eliminate
  usage of the nonstandard `-0` option

- Get rid of xargs where it isn’t strictly required, to avoid line
  length limits

GNUmakefile
README.markdown

index 5b341d69e59d1cc8a2c532f86c0af101c63a3bb8..6bf0c38fc0f200b0d08c51e42f4b4740963b6418 100644 (file)
@@ -43,7 +43,7 @@ override define makefileinfo
 ║│ • tr                                                       │║
 ║│ • uuencode                                                 │║
 ║│ • uudecode                                                 │║
 ║│ • tr                                                       │║
 ║│ • uuencode                                                 │║
 ║│ • uudecode                                                 │║
-║│ • xargs (requires support for `-0´)                        │║
+║│ • xargs                                                    │║
 ║│ • xmlcatalog (provided by libxml2)                         │║
 ║│ • xmllint (provided by libxml2)                            │║
 ║│ • xsltproc (provided by libxslt)                           │║
 ║│ • xmlcatalog (provided by libxml2)                         │║
 ║│ • xmllint (provided by libxml2)                            │║
 ║│ • xsltproc (provided by libxslt)                           │║
@@ -269,6 +269,14 @@ override modtime = $(shell if $(STAT) --version 2> /dev/null | $(GREP) -q GNU; t
 # (callable) Check to see if the given directory exists and create it if not.
 override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
 
 # (callable) Check to see if the given directory exists and create it if not.
 override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
 
+# Quote standard input in such a way that piping it to xargs will result in it being processed as a single argument.
+#
+# If standard input ends in a newline, it is stripped; all other newlines are preserved.
+override xargsquote = $(SED) $(call quote,s/'/'"'"'/g;s/^/'/;s/$$/'/;$$!s/$$/\\/)
+
+# Quote standard input in such a way that piping it to xargs will result in each line being processed as a single argument.
+override xargsmultiquote = $(SED) $(call quote,s/'/'"'"'/g;s/^/'/;s/$$/'/)
+
 # (callable) Test if the provided xpath expression matches the provided document.
 override xpath = $(XMLLINT) --xpath $(call quote,$1) $(call quote,$2) > /dev/null 2> /dev/null
 
 # (callable) Test if the provided xpath expression matches the provided document.
 override xpath = $(XMLLINT) --xpath $(call quote,$1) $(call quote,$2) > /dev/null 2> /dev/null
 
@@ -279,10 +287,10 @@ override extracttext = $(PRINTF) '%s' '<transform xmlns="http://www.w3.org/1999/
 override associatedfiles = $(LS) -1 $(call quote,$1) | $(SED) '/.*"{.*}".*/!d;s/^\(.*\)"{.*}"\(.*\)$$/\1\2|&/' | $(GREP) -F -e $(call quote,$2|) | $(SED) 's/^.*|//'
 
 # (callable) Remove files associated with the provided file.
 override associatedfiles = $(LS) -1 $(call quote,$1) | $(SED) '/.*"{.*}".*/!d;s/^\(.*\)"{.*}"\(.*\)$$/\1\2|&/' | $(GREP) -F -e $(call quote,$2|) | $(SED) 's/^.*|//'
 
 # (callable) Remove files associated with the provided file.
-override removeassociatedfiles = ASSOCIATED="$$($(call associatedfiles,$(dir $1),$(notdir $1)) | $(TR) '\n' ' ')"; if $(TEST) -n "$$ASSOCIATED"; then cd $(call quote,$(dir $1)) && $(PRINTF) '%s\n' "$$ASSOCIATED" | $(TR) ' ' '\n' | $(SED) $(call quote,/^$$/d;s/'/'"'"'/g;s/^/'/;s/$$/'/) | $(TR) '\n' ' ' | $(XARGS) $(RM); fi
+override removeassociatedfiles = ASSOCIATED="$$($(call associatedfiles,$(dir $1),$(notdir $1)) | $(TR) '\n' ' ')"; if $(TEST) -n "$$ASSOCIATED"; then cd $(call quote,$(dir $1)) && $(PRINTF) '%s\n' "$$ASSOCIATED" | $(SED) 's/ \{2,\}/ /g;s/^ //;s/ $$//' | $(TR) ' ' '\n' | $(xargsmultiquote) | $(XARGS) -E '' $(RM); fi
 
 # (callable) Process the provided transformation result and output the result to the provided location, given the provided relative path.
 
 # (callable) Process the provided transformation result and output the result to the provided location, given the provided relative path.
-override processresultto = if $(call xpath,/*[local-name()="raw-text" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(call extracttext,$1) > $(call quote,$2); $(call removeassociatedfiles,$2); elif $(call xpath,/*[local-name()="base64-binary" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(call extracttext,$1) | $(TR) -d '\t\n\f\r ' | $(XARGS) -0 $(PRINTF) 'begin-base64 644 -\n%s\n====\n' | $(UUDECODE) -o /dev/stdout > $(call quote,$2); $(call removeassociatedfiles,$2); elif $(call xpath,/*[local-name()="archive" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) $(call quote,$2) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/archive/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive'; $(call removeassociatedfiles,$2); elif $(call xpath,//*[local-name()="page" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) $(call quote,$2) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/paged/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:paged'; else $(XMLLINT) --nsclean $(call quote,$1) > $(call quote,$2); $(call removeassociatedfiles,$2);  fi
+override processresultto = if $(call xpath,/*[local-name()="raw-text" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(call extracttext,$1) > $(call quote,$2); $(call removeassociatedfiles,$2); elif $(call xpath,/*[local-name()="base64-binary" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(call extracttext,$1) | $(TR) -d '\t\n\f\r ' | $(SED) 's/^/begin-base64 644 -        /;s/$$/ ====/' | $(TR) '\t' '\n' | $(UUDECODE) -o /dev/stdout > $(call quote,$2); $(call removeassociatedfiles,$2); elif $(call xpath,/*[local-name()="archive" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) $(call quote,$2) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/archive/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive'; $(call removeassociatedfiles,$2); elif $(call xpath,//*[local-name()="page" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) $(call quote,$2) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/paged/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:paged'; else $(XMLLINT) --nsclean $(call quote,$1) > $(call quote,$2); $(call removeassociatedfiles,$2);  fi
 
 # ━ § BEGIN DEFAULT MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
 
 # ━ § BEGIN DEFAULT MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
@@ -303,7 +311,7 @@ override diffprereqs = $(if $(subst $(shell $(CAT) $(call quote,$(BUILDDIR)/last
 override sedesc = $(subst /,[/],$(subst $$,\$$,$(subst *,\*,$(subst .,\.,$(subst [,\[,$(subst ^,\^,$(subst \,\\,$1)))))))
 
 # The command to use for percent‐decoding.
 override sedesc = $(subst /,[/],$(subst $$,\$$,$(subst *,\*,$(subst .,\.,$(subst [,\[,$(subst ^,\^,$(subst \,\\,$1)))))))
 
 # The command to use for percent‐decoding.
-override perdeccmd := $(SED) 's/|/%7C/g;s/[\]/%5C/g;s/%[0-9A-Fa-f]\{2\}/|&|/g' | $(TR) '|' '\n' | $(SED) '/^%[0-9A-Fa-f]\{2\}$$/!s/%/|%25|/' | $(TR) '|' '\n' | $(AWK) '$$0!~/%/{printf "%s",$$0}/%/{d="0123456789ABCDEF";v=substr(toupper($$0),2,2);printf "\\%04o",(index(d,substr(v,1,1))-1)*16+index(d,substr(v,2,1))-1}' | $(XARGS) -0 $(PRINTF) '%b'
+override perdeccmd := $(SED) 's/|/%7C/g;s/[\]/%5C/g;s/%[0-9A-Fa-f]\{2\}/|&|/g' | $(TR) '|' '\n' | $(SED) '/^%[0-9A-Fa-f]\{2\}$$/!s/%/|%25|/' | $(TR) '|' '\n' | $(AWK) '$$0!~/%/{printf "%s",$$0}/%/{d="0123456789ABCDEF";v=substr(toupper($$0),2,2);printf "\\%04o",(index(d,substr(v,1,1))-1)*16+index(d,substr(v,2,1))-1}' | $(xargsquote) | $(XARGS) -E '' $(PRINTF) '%b'
 
 # (callable) Percent‐decode the given strings.
 #
 
 # (callable) Percent‐decode the given strings.
 #
@@ -466,7 +474,7 @@ endif
 override id = $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $(call quote,$1) 2> /dev/null || $(PRINTF) '%s\n' $(call quote,about:shushe?$(or $2,unknown)=$(call pathenc,$(basename $(notdir $1))))
 
 # (callable) Sanitize and wrap the provided plaintext file in X·M·L, printing to `stdout´.
 override id = $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $(call quote,$1) 2> /dev/null || $(PRINTF) '%s\n' $(call quote,about:shushe?$(or $2,unknown)=$(call pathenc,$(basename $(notdir $1))))
 
 # (callable) Sanitize and wrap the provided plaintext file in X·M·L, printing to `stdout´.
-override wrapplaintext = $(TR) '\000\013\014' '\032\011\012' < $(call quote,$1) | $(SED) "$$($(PRINTF) '%b' 's/]]>/]]]]><!\\[CDATA\\[>/g\ns/\0357\0277\0276/�/g\ns/\0357\0277\0277/�/g\n$$!s/\\r$$//g\ns/\\r/\\n/g\n$$!s/\0302\0205$$//g\ns/\0302\0205/\\n/g;s/\0342\0200\0250/\\n/g;s/[\0001-\0010]/�/g;s/[\0016-\0037]/�/g')" | $(XARGS) -0 $(PRINTF) '%b%s]]></script>\n' '<?xml version=\042\061.0\042?>\n<script xmlns=\042http://www.w3.org/1999/xhtml\042 type=\042$(call typeoffile,$1)\042><![CDATA['
+override wrapplaintext = $(TR) '\000\013\014' '\032\011\012' < $(call quote,$1) | $(SED) "$$($(PRINTF) '%b' 's/]]>/]]]]><!\\[CDATA\\[>/g\ns/\0357\0277\0276/�/g\ns/\0357\0277\0277/�/g\n$$!s/\\r$$//g\ns/\\r/\\n/g\n$$!s/\0302\0205$$//g\ns/\0302\0205/\\n/g\ns/\0342\0200\0250/\\n/g\ns/[\0001-\0010]/�/g\ns/[\0016-\0037]/�/g\n1s|^|<?xml version=\0042\0061.0\0042?>\\n<script xmlns=\0042http://www.w3.org/1999/xhtml\0042 type=\0042$(call typeoffile,$1)\0042><![CDATA[|\n$$s|$$|]]></script>|')"
 
 # (callable) Check if the provided X·M·L file is X·M·L 1.1, and if so, coerce to X·M·L 1.0 as best as possible, printing the result (or the original file contents) to `stdout´.
 #
 
 # (callable) Check if the provided X·M·L file is X·M·L 1.1, and if so, coerce to X·M·L 1.0 as best as possible, printing the result (or the original file contents) to `stdout´.
 #
@@ -577,7 +585,7 @@ $(BUILDDIR)/magic.mgc : $(call diffprereqs,magic,$(sort $(call magicfile,$(MAGIC
 $(BUILDDIR)/parser.catalog : $(call diffprereqs,parsers,$(sort $(PARSERS)))
        @$(ECHO) "Generating catalog of parsers…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
 $(BUILDDIR)/parser.catalog : $(call diffprereqs,parsers,$(sort $(PARSERS)))
        @$(ECHO) "Generating catalog of parsers…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-       $(foreach parser,$(PARSERS),$(silent)( $(call id,$(parser)) ) | $(XARGS) -I %% $(XMLCATALOG) --add uri %% $(call quote,$(call fileuri,$(parser))) --noout $(call quote,$@)$(newline))
+       $(foreach parser,$(PARSERS),$(silent){ $(call id,$(parser)); printf '%s\n' $(call quote,$(call fileuri,$(parser))) '--noout' $(call quote,$@); } | $(xargsmultiquote) | $(XARGS) -E '' $(XMLCATALOG) --add uri$(newline))
 $(BUILDDIR)/parser.xslt : $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt
        @$(ECHO) "Generating main parser…"
        $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<)
 $(BUILDDIR)/parser.xslt : $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt
        @$(ECHO) "Generating main parser…"
        $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<)
@@ -619,7 +627,7 @@ $(BUILDDIR)/destinations : $(BUILDDIR)/catalog $(call parsed,$(filter-out $(asse
 $(BUILDDIR)/transform.catalog : $(call diffprereqs,transforms,$(sort $(TRANSFORMS)))
        @$(ECHO) "Generating catalog of transforms…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
 $(BUILDDIR)/transform.catalog : $(call diffprereqs,transforms,$(sort $(TRANSFORMS)))
        @$(ECHO) "Generating catalog of transforms…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-       $(foreach transform,$(TRANSFORMS),$(silent)( $(call id,$(transform)) ) | $(XARGS) -I %% $(XMLCATALOG) --add uri %% $(call quote,$(call fileuri,$(transform))) --noout $(call quote,$@)$(newline))
+       $(foreach transform,$(TRANSFORMS),$(silent){ $(call id,$(transform)); printf '%s\n' $(call quote,$(call fileuri,$(transform))) '--noout' $(call quote,$@); } | $(xargsmultiquote) | $(XARGS) -E '' $(XMLCATALOG) --add uri$(newline))
 $(BUILDDIR)/transform.xslt : $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt
        @$(ECHO) "Generating main transform…"
        $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<)
 $(BUILDDIR)/transform.xslt : $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt
        @$(ECHO) "Generating main transform…"
        $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<)
@@ -645,7 +653,7 @@ $(call installed,$(recursivefiles) $(installablefiles)) : $(DESTDIR)/% : $(BUILD
        @$(PRINTF) '%s\n' $(call quote,Installing </$*>…)
        $(silent)$(call ensuredirectory,$(dir $@))
        $(silent)$(CP) $(call quote,$<) $(call quote,$@)
        @$(PRINTF) '%s\n' $(call quote,Installing </$*>…)
        $(silent)$(call ensuredirectory,$(dir $@))
        $(silent)$(CP) $(call quote,$<) $(call quote,$@)
-       $(silent)for associated in $$($(call associatedfiles,$(dir $<),$(notdir $<))); do $(PRINTF) '%s\n' "$$associated" | $(SED) 's/^\(.*\)"{\(.*\)}"\(.*\)$$/\1\2\3/' | $(XARGS) -0 $(PRINTF) '%s%s\n' $(call quote,$(dir $@)) | $(XARGS) -0 $(CP) $(call quote,$(dir $<))"$$associated"; done
+       $(silent)for associated in $$($(call associatedfiles,$(dir $<),$(notdir $<))); do $(PRINTF) '%s\n' "$$associated" | $(SED) 's/^\(.*\)"{\(.*\)}"\(.*\)$$/\1\2\3/' | $(xargsquote) | $(XARGS) -E '' $(PRINTF) '%s%s\n' $(call quote,$(dir $@)) | $(xargsquote) | $(XARGS) -E '' $(CP) $(call quote,$(dir $<))"$$associated"; done
 
 # ━ § BEGIN ARCHIVE MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
 
 # ━ § BEGIN ARCHIVE MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
index bf353e0f0266f768cac8d2c48b8de8b0426e451c..b83d49ecd24272d33ece6f19ec210683e4133492 100644 (file)
@@ -122,14 +122,6 @@ These are Posix utilities, but not included in the Linux Standard Base
 The G·N·U [Sharutils](https://www.gnu.org/software/sharutils/) package
   can be installed to access them.
 
 The G·N·U [Sharutils](https://www.gnu.org/software/sharutils/) package
   can be installed to access them.
 
-### `xargs`
-
-This is a Posix utility, but ⛩️📰 书社 currently depends on
-  unspecified behaviour.
-It requires support for the `-0` flag, which must disable the special
-  quote and whitespace handling of `xargs` in favour of null‐terminated
-  strings.
-
 ### `xmlcatalog` and `xmllint`
 
 These are not a Posix utilities.
 ### `xmlcatalog` and `xmllint`
 
 These are not a Posix utilities.
@@ -227,7 +219,7 @@ In every case, you may supply your own implementation by overriding the
 - `tr`
 - `uuencode`
 - `uudecode`
 - `tr`
 - `uuencode`
 - `uudecode`
-- `xargs` (requires support for `-0`)
+- `xargs`
 - `xmlcatalog` (provided by `libxml2`)
 - `xmllint` (provided by `libxml2`)
 - `xsltproc` (provided by `libxslt`)
 - `xmlcatalog` (provided by `libxml2`)
 - `xmllint` (provided by `libxml2`)
 - `xsltproc` (provided by `libxslt`)
This page took 0.034299 seconds and 4 git commands to generate.