]> Lady’s Gitweb - Shushe/commitdiff
Enable output redirection with 书社:destination 0.3.0
authorLady <redacted>
Tue, 16 Jan 2024 05:07:00 +0000 (00:07 -0500)
committerLady <redacted>
Thu, 18 Jan 2024 02:36:51 +0000 (21:36 -0500)
Specifying this attribute on the root element (after parsing, but
before transformation) will override the default output location. All
of the processing for this can be done at the same time as dependency
detection, as it depends on media typing but not on the dependency
tree.

GNUmakefile
README.markdown
lib/catalog2dependencies.xslt
lib/catalog2destinations.xslt [new file with mode: 0644]
lib/catalog2transform.xslt

index 085b4c28d0428365aa6fe6dd858623774be27e4a..937ada5b8659df0318864f8a97956b510401a27a 100644 (file)
@@ -14,6 +14,7 @@ override define makefileinfo
 ║│ version incompatibilities. The full list of program        │║
 ║│ requirements is as follows :—                             │║
 ║│                                                            │║
+║│ • awk                                                      │║
 ║│ • cat                                                      │║
 ║│ • cp                                                       │║
 ║│ • date                                                     │║
@@ -22,6 +23,7 @@ override define makefileinfo
 ║│ • find                                                     │║
 ║│ • mkdir (requires support for `-p´)                        │║
 ║│ • mv                                                       │║
+║│ • od (requires support for `-t x1´)                        │║
 ║│ • printf                                                   │║
 ║│ • rm                                                       │║
 ║│ • sed                                                      │║
@@ -31,6 +33,7 @@ override define makefileinfo
 ║│ • touch                                                    │║
 ║│ • tr (requires support for `-d´)                           │║
 ║│ • uuencode (requires support for `-m´ and `-r´)            │║
+║│ • xargs (requires support for `-0´)                        │║
 ║│ • xmlcatalog (provided by libxml2)                         │║
 ║│ • xmllint (provided by libxml2)                            │║
 ║│ • xsltproc (provided by libxslt)                           │║
@@ -79,6 +82,7 @@ endef
 #
 # If these are not installed on your computer, or you need to use a
 # different implementation, you can override the appropriate variable.
+AWK := awk
 CAT := cat
 CP := cp
 DATE := date
@@ -87,6 +91,7 @@ FILE := file
 FIND := find
 MKDIR := mkdir
 MV := mv
+OD := od
 PRINTF := printf
 RM := rm
 SED := sed
@@ -96,6 +101,7 @@ TEST := test
 TOUCH := touch
 TR := tr
 UUENCODE := uuencode
+XARGS := xargs
 XMLCATALOG := xmlcatalog
 XMLLINT := xmllint
 XSLTPROC := xsltproc
@@ -143,9 +149,7 @@ MAGICDIR := $(patsubst ./%,%,$(THISDIR)/magic)
 # By default, `find´ will not follow symlinks and will use extended
 # regular expressions, ignoring hidden files and those which begin with
 # a period.
-FINDOPTS := -PE
-FINDRULES := -flags -nohidden -and -not -name '.*'
-FINDINCLUDEOPTS := $(FINDOPTS)
+FINDRULES := -flags -nohidden -and ! '(' '(' -name '[.-]*' -or -name '*[:|$$%]*' ')' -and -prune ')'
 FINDINCLUDERULES := $(FINDRULES)
 
 # The list of parsers for plaintext file types.
@@ -203,6 +207,21 @@ override silent := $(if $(VERBOSE),,@)
 # expressions.
 override sedesc = $(subst /,[/],$(subst $$,\$$,$(subst *,\*,$(subst .,\.,$(subst [,\[,$(subst ^,\^,$(subst \,\\,$1)))))))
 
+# (callable) Percent‐decode the given strings.
+override perdec = $(foreach encoded,$1,$(shell $(PRINTF) '%s\n' $(call quote,$(encoded)) | $(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)}/%/{sub("%","0x");printf("\\%04o",$$0)}' | $(XARGS) -0 $(PRINTF) '%b'))
+
+# (callable) Percent‐encode the given strings.
+#
+# This singly‐encodes u·r·i characters and doubly‐encodes other
+# characters, then calls `perdec´ to decode back to a single encoding.
+# The encoding assumes the input is a “u·r·i component”; e·g that the
+# resulting string should only contain `pchar´ (but can contain any
+# `sub-delim´).
+override perenc = $(foreach unencoded,$1,$(call perdec,$(shell $(PRINTF) '%s' $(call quote,$(unencoded)) | $(OD) -t x1 | $(SED) 's/^[0-9]*//;s/2[146-9A-Ea-e]/%&/g;s/3[0-9AaBbDd]/%&/g;s/40/%&/g;s/[46][1-9A-Fa-f]/%&/g;s/[57][0-9Aa]/%&/g;s/7[Ee]/%&/g;s/[ ][0-9A-Fa-f]\{2\}/%25&/g' | $(TR) -d ' \n' | $(TR) 'abcdef' 'ABCDEF')))
+
+# (callable) Percent‐encode each component in the given paths.
+override pathenc = $(foreach path,$1,$(subst $(space),/,$(call perenc,$(subst /, ,$(path)))))
+
 # (overridable) Collect all of the applicable includes from the
 # includes directory.
 sourceincludes := $(shell $(FIND) $(FINDOPTS) $(INCLUDEDIR) -type f '(' $(FINDRULES) ')')
@@ -213,7 +232,7 @@ sourcefiles := $(filter-out $(sourceincludes),$(shell $(FIND) $(FINDOPTS) $(SRCD
 
 # Figure out the file type of each source file and source include.
 ifneq ($(wildcard $(BUILDDIR)/magic.mgc),)
-override types := $(shell $(SED) 's/^ *//;s/ *$$//;s/ {2,}/ /g' <<< $(call quote,$(sourcefiles) $(sourceincludes)) | $(TR) ' ' '\n' | $(FILE) -m $(call quote,$(BUILDDIR)/magic.mgc) --mime-type --separator '`' --files-from - | $(SED) 's/` */?type=/g')
+override types := $(shell $(SED) 's/^ *//;s/ *$$//;s/ {2,}/ /g' <<< $(call quote,$(sourcefiles) $(sourceincludes)) | $(TR) ' ' '\n' | $(FILE) -m $(call quote,$(BUILDDIR)/magic.mgc) --mime-type --separator '|' --files-from - | $(SED) 's/| */|/g')
 endif
 
 # Get the list of supported plaintext file types from the parser.
@@ -223,7 +242,7 @@ endif
 
 # (callable) Get all of the files (source and includes) which have the
 # given types.
-override filesoftype = $(foreach type,$1,$(patsubst %?type=$(type),%,$(filter %?type=$(type),$(types))))
+override filesoftype = $(foreach type,$1,$(patsubst %|$(type),%,$(filter %|$(type),$(types))))
 
 # Build up collections of various file types.
 override xmlfiles := $(call filesoftype,$(XMLTYPES))
@@ -231,10 +250,10 @@ override plaintextfiles := $(filter-out $(xmlfiles),$(call filesoftype,$(plainte
 override assetfiles := $(filter-out $(xmlfiles) $(plaintextfiles),$(sourcefiles) $(sourceincludes))
 
 # (callable) Get the types of the given files.
-override typeoffile = $(patsubst $(foreach file,$1,$(file)?type=%),%,$(filter $(foreach file,$1,$(file)?type=%),$(types)))
+override typeoffile = $(patsubst $(foreach file,$1,$(file)|%),%,$(filter $(foreach file,$1,$(file)|%),$(types)))
 
 # (callable) Get the identifier for the given transform.
-override id = $(or $(shell $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $1),$(basename $(notdir $1)) | $(SED))
+override id = $(or $(shell $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $1),example:$(call pathenc,$(basename $(notdir $1))))
 
 # (callable) Get the local path for the given source file.
 override sourcepath = $(firstword $(foreach directory,$(SRCDIR),$(if $(filter $(directory)/%,$1),$(patsubst $(directory)/%,%,$1),)))
@@ -245,14 +264,14 @@ override includepath = $(firstword $(foreach directory,$(INCLUDEDIR),$(if $(filt
 # (callable) Get base64 data u·r·i’s for the given files.
 override datauri = $(foreach file,$1,data:$(call typeoffile,$(file));base64,$(shell $(UUENCODE) -m -r $(call quote,$(file)) _ | tr -d ' \n'))
 
-# (callable) Get local leiris for the given files.
-override localuri = $(foreach file,$1,$(if $(filter $(file),$(sourceincludes)),about:shushe?include=$(call includepath,$(file)),about:shushe?source=$(call sourcepath,$(file))))
-
 # Pair each source file and include with its local u·r·i.
-override sourcelocalpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(file)`$(call localuri,$(file)))
+override sourcelocalpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|about:shushe?$(if $(filter $(file),$(sourceincludes)),include=$(call pathenc,$(call includepath,$(file))),source=$(call pathenc,$(call sourcepath,$(file)))))
 
-# (callable) Get the source files for the given local leiris.
-override sourcefile = $(foreach local,$1,$(patsubst %`$(local),%,$(filter %`$(local),$(sourcelocalpair))))
+# (callable) Get local uris for the given files.
+override localuri = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcelocalpair))))
+
+# (callable) Get the source files for the given local uris.
+override sourcefile = $(foreach local,$1,$(patsubst %|$(local),%,$(filter %|$(local),$(sourcelocalpair))))
 
 # Adds a requirement on `$(BUILDDIR)/.update-types´ if the file is
 # present.
@@ -262,33 +281,33 @@ override sourcefile = $(foreach local,$1,$(patsubst %`$(local),%,$(filter %`$(lo
 # up‐to‐date immediately after the reload.
 override typeupdates := $(wildcard $(BUILDDIR)/.update-types)
 
+# Pair each source file and include with its parsed location.
+override sourceparsedpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/$(if $(filter $(file),$(sourceincludes)),includes/$(call includepath,$(file)),sources/$(call sourcepath,$(file))))
+
 # (callable) Get the location of the transformed X·M·L files for the
 # given source files.
-override parsed = $(foreach file,$1,$(if $(filter $(file),$(sourceincludes)),$(BUILDDIR)/includes/$(call includepath,$(file)),$(BUILDDIR)/sources/$(call sourcepath,$(file))))
-
-# Pair each source file and include with its parsed location.
-override sourceparsedpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(file)`$(call parsed,$(file)))
+override parsed = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourceparsedpair))))
 
 # (callable) Get the source files for the given parsed file.
-override unparsed = $(foreach file,$1,$(patsubst %`$(file),%,$(filter %`$(file),$(sourceparsedpair))))
+override unparsed = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourceparsedpair))))
 
 ifneq ($(wildcard $(BUILDDIR)/dependencies),)
 # Pair each file with a list of dependencies for it.
-override dependenciesforfile := $(foreach file,$(sourcefiles),$(file)`$(subst $(space),`,$(shell $(CAT) $(call quote,$(BUILDDIR)/dependencies) | $(SED) $(call quote,/^$(call sedesc,$(call localuri,$(file)))$$/$(comma)/^[^  ]/!d;/^ /!d;s/^ //))))
+override dependenciesforfile := $(foreach file,$(sourcefiles),$(file)|$(subst $(space),|,$(shell $(CAT) $(call quote,$(BUILDDIR)/dependencies) | $(SED) $(call quote,/^$(call sedesc,$(call localuri,$(file)))$$/$(comma)/^[^  ]/!d;/^ /!d;s/^ //))))
 
 # (callable) Get the list of dependency leiris for the given source
 # files.
 #
-# Recursive dependencies are marked with a leading `!´.
-override dependencyuris = $(foreach file,$1,$(subst `, ,$(patsubst $(file)`%,%,$(filter $(file)`%,$(dependenciesforfile)))))
+# Recursive dependencies are marked with a leading `-´.
+override dependencyuris = $(foreach file,$1,$(subst |, ,$(patsubst $(file)|%,%,$(filter $(file)|%,$(dependenciesforfile)))))
 
 # (callable) Get the list of recursive dependencies for the given
 # source files.
-override recursives = $(foreach uri,$(filter !%,$(call dependencyuris,$1)),$(call sourcefile,$(patsubst !%,%,$(uri))))
+override recursives = $(foreach uri,$(filter -%,$(call dependencyuris,$1)),$(call sourcefile,$(patsubst -%,%,$(uri))))
 
 # (callable) Get the list of (nonrecursive) dependencies for the given
 # source files.
-override dependencies = $(foreach uri,$(filter-out !%,$(call dependencyuris,$1)),$(call sourcefile,$(uri)))
+override dependencies = $(foreach uri,$(filter-out -%,$(call dependencyuris,$1)),$(call sourcefile,$(uri)))
 endif
 
 # Collect all files with recursive dependencies.
@@ -299,17 +318,29 @@ override recursivefiles := $(foreach file,$(filter-out $(assetfiles),$(sourcefil
 # This is all of the non·asset, nonrecursive files.
 override compilablefiles := $(filter-out $(assetfiles) $(recursivefiles),$(sourcefiles))
 
-# (callable) Get the compiled locations for the given source files.
-override compiled = $(foreach file,$1,$(BUILDDIR)/public/$(call sourcepath,$(file)))
+ifneq ($(wildcard $(BUILDDIR)/destinations),)
+# Get the output of the destination transform.
+override destinations := $(shell $(CAT) $(BUILDDIR)/destinations)
+
+# Pair source files and their destinations.
+override sourcedestinationpair := $(foreach destination,$(destinations),$(call sourcefile,$(firstword $(subst |, ,$(destination))))|$(call perdec,$(subst $(space),|,$(wordlist 2,$(words $(subst |, ,$(destination))),$(subst |, ,$(destination))))))
+
+# (callable) Get the destination for the given source files.
+override destination = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair))))
 
 # Pair each source file and include with its compiled location.
-override sourcecompiledpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(file)`$(call compiled,$(file)))
+override sourcecompiledpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/public/$(call destination,$(file)))
+
+# (callable) Get the location of the transformed X·M·L files for the
+# given source files.
+override compiled = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcecompiledpair))))
 
 # (callable) Get the source files for the given compiled file.
-override uncompiled = $(foreach file,$1,$(patsubst %`$(file),%,$(filter %`$(file),$(sourcecompiledpair))))
+override uncompiled = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourcecompiledpair))))
 
 # (callable) Get the installed locations for the given source files.
-override installed = $(foreach file,$1,$(DESTDIR)/$(call sourcepath,$(file)))
+override installed = $(foreach file,$1,$(DESTDIR)/$(call destination,$(file)))
+endif
 
 # ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
 
@@ -319,7 +350,7 @@ override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(
 
 # (callable) Sanitize and wrap the provided plaintext file in
 #  X·M·L, printing to `stdout´.
-override wrapplaintext = $(PRINTF) '%s\n' "$$($(PRINTF) '%b' '<?xml version=\042\061.0\042?>\n<script xmlns=\042http://www.w3.org/1999/xhtml\042 type=\042$(patsubst $1?type=%,%,$(filter $1?type=%,$(types)))\042><![CDATA['; $(CAT) $(call quote,$1) | $(TR) '\000\013\014' '\032\011\012' | $(SED) $$($(PRINTF) '%s%b' 's/]]>/]]]]><!\[CDATA\[>/g;s/\xEF\xBF\xBE/�/g;s/\xEF\xBF\xBF/�/g;$$!s/\r$$//g;s/\r/\n/g;$$!s/\xC2\x85$$//g;s/\xC2\x85/\n/g;s/\xE2\x80\xA8/\n/g;' 's/[\0001-\0010]/�/g;s/[\0016-\0037]/�/g'); $(PRINTF) '%s' ']]></script>')"
+override wrapplaintext = $(PRINTF) '%s\n' "$$($(PRINTF) '%b' '<?xml version=\042\061.0\042?>\n<script xmlns=\042http://www.w3.org/1999/xhtml\042 type=\042$(call typeoffile,$1)\042><![CDATA['; $(CAT) $(call quote,$1) | $(TR) '\000\013\014' '\032\011\012' | $(SED) $$($(PRINTF) '%s%b' 's/]]>/]]]]><!\[CDATA\[>/g;s/\xEF\xBF\xBE/�/g;s/\xEF\xBF\xBF/�/g;$$!s/\r$$//g;s/\r/\n/g;$$!s/\xC2\x85$$//g;s/\xC2\x85/\n/g;s/\xE2\x80\xA8/\n/g;' 's/[\0001-\0010]/�/g;s/[\0016-\0037]/�/g'); $(PRINTF) '%s' ']]></script>')"
 
 # ─ ¶ Phony Targets ───────────────────────────────────────────────────
 
@@ -343,12 +374,12 @@ install: $(call installed,$(recursivefiles) $(compilablefiles) $(filter $(source
 
 # List all source files and includes and their computed types.
 list:
-       $(silent)$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m`$(call typeoffile,$(file))`[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)), include,)\0033[23m]$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•`Recursive`Dependency:\0033[39;49m`$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•`Dependency:\0033[22m`$(dependency)))) )) | $(TR) ' `' '\n '
+       $(silent)$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m|$(call typeoffile,$(file))|[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)),|include,)\0033[23m]$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•|Recursive|Dependency|\0033[39;49m|$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•|Dependency|\0033[22m|$(dependency))))$(if $(filter $(file),$(sourcefiles)), →|<\0033[4m/$(call destination,$(file))\0033[24m>,) )) | $(TR) ' |' '\n '
 
 # Raise an error when attempting to build any files with recursive
 # dependencies.
-$(call compiled,$(recursivefiles)): $(BUILDDIR)/public/%:
-       @$(PRINTF) '%b\n' $(call quote,\0033[93;41mError:\0033[39;49m `$*´ has recursive dependencies:\n$(subst `, ,$(subst $(space),$(newline),$(foreach recursive,$(call recursives,$(SRCDIR)/$*),•`$(patsubst $(SRCDIR)/%,%,$(recursive)))))) && false
+$(call compiled,$(recursivefiles)):
+       @$(PRINTF) '%b\n' $(call quote,\0033[93;41mError:\0033[39;49m `$(call uncompiled,$@)´ has recursive dependencies:\n$(subst |, ,$(subst $(space),$(newline),$(foreach recursive,$(call recursives,$(call uncompiled,$@)),•|$(recursive))))) && false
 
 # ─ ¶ Special Targets ─────────────────────────────────────────────────
 
@@ -371,10 +402,10 @@ ifneq ($(wildcard $(BUILDDIR)/.update-types)$(wildcard $(BUILDDIR)/dependencies)
 #
 # This recipe only exists after types have been updated or when the
 # dependency graph already exists.
-$(THISDIR)/GNUmakefile:: $(BUILDDIR)/dependencies
+$(THISDIR)/GNUmakefile:: $(BUILDDIR)/dependencies $(BUILDDIR)/destinations
        $(silent)$(TOUCH) $(THISDIR)/GNUmakefile
        $(silent)$(RM) -f $(BUILDDIR)/.update-types
-       @$(PRINTF) '%b\n' '\0033[1mDependency graph updated. Restarting…\0033[22m'
+       @$(PRINTF) '%b\n' '\0033[1mDependency graph and output destinations updated. Restarting…\0033[22m'
 endif
 
 ifeq ($(wildcard $(BUILDDIR)/.update-types),)
@@ -410,7 +441,7 @@ $(BUILDDIR)/magic.mgc: $(wildcard $(MAGICDIR)/*)
 $(BUILDDIR)/parser.catalog: $(PARSERS)
        @$(ECHO) "Generating catalog of parsers…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-       $(foreach parser,$(PARSERS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(parser))) $(call quote,../$(parser)) --noout $(call quote,$@)$(newline))
+       $(foreach parser,$(PARSERS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(parser))) $(call quote,$(call pathenc,../$(parser))) --noout $(call quote,$@)$(newline))
 $(BUILDDIR)/parser.xslt: $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt
        @$(ECHO) "Generating main parser…"
        $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<)
@@ -425,23 +456,30 @@ $(call parsed,$(sourcefiles) $(sourceincludes)): %: $$(call unparsed,$$@) $(type
        $(silent)$(call ensuredirectory,$(dir $@))
        $(silent)$(if $(filter $<,$(assetfiles)),$(PRINTF) '%s\n' $(call quote,<object xmlns="http://www.w3.org/1999/xhtml" type="$(call typeoffile,$<)" data="$(call datauri,$<)"/>) > $(call quote,$@),$(if $(filter $<,$(plaintextfiles)),$(call wrapplaintext,$<),$(CAT) $(call quote,$<)) | $(XSLTPROC) -o $(call quote,$@) $(call quote,$(BUILDDIR)/parser.xslt) -)
 
-# Generate a catalog of all transformed files, for use when processing
+# Generate a catalog of all parsed files, for use when processing
 # includes. This does not depend on actually transforming the files.
 $(BUILDDIR)/catalog: $(sourcefiles) $(sourceincludes) $(typeupdates)
        @$(ECHO) "Generating catalog of parsed files…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-       $(foreach source,$(sourcefiles) $(sourceincludes),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call localuri,$(source))) $(call quote,$(patsubst $(BUILDDIR)/%,%,$(call parsed,$(source)))#$(if $(filter $(source),$(assetfiles)),asset,xml)) --noout $(call quote,$@)$(newline))
+       $(foreach source,$(sourcefiles) $(sourceincludes),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call localuri,$(source))) $(call quote,$(call pathenc,$(patsubst $(BUILDDIR)/%,%,$(call parsed,$(source))))#$(if $(filter $(source),$(assetfiles)),asset,xml)) --noout $(call quote,$@)$(newline))
 
-# Build a list of dependencies for each transformed file.
+# Build a list of dependencies for each parsed file.
 $(BUILDDIR)/dependencies: $(BUILDDIR)/catalog $(call parsed,$(plaintextfiles) $(xmlfiles)) $(THISDIR)/lib/catalog2dependencies.xslt
        @$(ECHO) "Identifying dependencies…"
        $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2dependencies.xslt) $(call quote,$<)
 
+# Generate a catalog of destinations for files. This depends on parsing
+# non·asset source files, but not assets or includes. It does not
+# require knowing the dependencies.
+$(BUILDDIR)/destinations: $(BUILDDIR)/catalog $(call parsed,$(filter-out $(assetfiles),$(sourcefiles))) $(THISDIR)/lib/catalog2destinations.xslt
+       @$(ECHO) "Identifying output destinations…"
+       $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2destinations.xslt) $(call quote,$<)
+
 # Generate the main transform.
 $(BUILDDIR)/transform.catalog: $(TRANSFORMS)
        @$(ECHO) "Generating catalog of transforms…"
        $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-       $(foreach transform,$(TRANSFORMS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(transform))) $(call quote,../$(transform)) --noout $(call quote,$@)$(newline))
+       $(foreach transform,$(TRANSFORMS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(transform))) $(call quote,$(call pathenc,../$(transform))) --noout $(call quote,$@)$(newline))
 $(BUILDDIR)/transform.xslt: $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt
        @$(ECHO) "Generating main transform…"
        $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<)
index 89dfd2efddc97526a4dbb4448ffff77f1a82dd94..de822096c943ddfeae790ae9cda2469fd9be43f3 100644 (file)
@@ -91,6 +91,7 @@ In every case, you may supply your own implementation by overriding the
   corresponding (allcaps) variable (e·g, set `MKDIR` to supply your own
   `mkdir` implementation).
 
+- `awk`
 - `cat`
 - `cp`
 - `date`
@@ -99,6 +100,7 @@ In every case, you may supply your own implementation by overriding the
 - `find`
 - `mkdir` (requires support for `-p`)
 - `mv`
+- `od` (requires support for `-t x1`)
 - `printf`
 - `rm`
 - `sed`
@@ -108,6 +110,7 @@ In every case, you may supply your own implementation by overriding the
 - `touch`
 - `tr` (requires support for `-d`)
 - `uuencode` (requires support for `-m` and `-r`)
+- `xargs` (requires support for `-0`)
 - `xmlcatalog` (provided by `libxml2`)
 - `xmllint` (provided by `libxml2`)
 - `xsltproc` (provided by `libxslt`)
@@ -154,17 +157,10 @@ The following additional variables can be used to control the behaviour
 - **`MAGICDIR`:**
   The location of the magic files to use (default: `$(THISDIR)/magic`).
 
-- **`FINDOPTS`:**
-  Options to pass to `find` when searching for source files (default:
-    `-PE`).
-
 - **`FINDRULES`:**
-  Rules to use with `find` when searching for source files (default:
-    `-flags -nohidden -and -not -name '.*'`).
-
-- **`FINDINCLUDEOPTS`:**
-  Options to pass to `find` when searching for includes (default:
-    `$(FINDOPTS)`).
+  Rules to use with `find` when searching for source files.
+  The default ignores hidden files, those that start with a period or
+    hyphen‐minus, and those which contain a pipe, buck, or colon.
 
 - **`FINDINCLUDERULES`:**
   Rules to use with `find` when searching for includes (default:
@@ -210,11 +206,12 @@ Text formats with associated X·S·L·T parsers are wrapped in a H·T·M·L
 Source files whose media type does not have an associated X·S·L·T
   parser are considered “assets” and will not be transformed.
 
-For compatibility with this program, source filenames should not
-  contain Ascii whitespace or any of the following Ascii characters:
-  ``!"#$%&()-:<>?\^`{|}``.
-These characters are either invalid in u·r·i’s or conflict with aspects
-  of the Make or commandline syntax.
+**☡ For compatibility with this program, source filenames must not
+  contain Ascii whitespace, colons (`:`), pipes (`|`), bucks (`$`),
+  percents (`%`) or control characters, and must not begin with a
+  hyphen‐minus (`-`).**
+The former characters have the potential to conflict with make syntax,
+  and a leading hyphen‐minus is confusable for a command‐line argument.
 
 ## Parsers
 
@@ -307,6 +304,15 @@ Embedding takes place after parsing but before transformation, so
   and update them accordingly; it will signal an error if the
   dependencies are recursive.
 
+## Output Redirection
+
+By default, ⛩️📰 书社 installs files to the same location in `DESTDIR`
+  as they were placed in their `SRCDIR`.
+This behaviour can be customized by setting the `@书社:destination`
+  attribute on the root element, whose value can give a different path.
+This attribute is read after parsing, but before transformation (where
+  it is silently dropped).
+
 ## Transforms
 
 Transforms are used to convert X·M·L files into their final output,
@@ -382,7 +388,7 @@ In addition to being called with the transform result, each of these
   modes will additionally be called with a `<xslt:include>` element
   corresponding to each transform.
 If a transform has a `<书社:id>` top‐level element whose value is an
-  i·r·i, its `<xslt:import>` element will have a corresponding
+  i·r·i, its `<xslt:include>` element will have a corresponding
   `@书社:id` attribute.
 This mechanism can be used to allow transforms to insert content
   without matching any elements in the result; for example, the
index b1e54a1f3d6cb02fdd7f35df66d4ddd1795a4345..3d36949fb237f05d123595931f394dfc79a0c3d1 100644 (file)
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ lib/catalog2dependencies.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s Computer]
 
 This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
 If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
@@ -98,7 +98,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        <text>&#xA;</text>
                        <for-each select="exsl:node-set($dependencies)/书社:recursive-dependency">
                                <text>&#x9;</text>
-                               <text>!</text>
+                               <text>-</text>
                                <value-of select="."/>
                                <text>&#xA;</text>
                        </for-each>
diff --git a/lib/catalog2destinations.xslt b/lib/catalog2destinations.xslt
new file mode 100644 (file)
index 0000000..cadb0c3
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+⁌ ⛩️📰 书社 ∷ lib/catalog2destinations.xslt
+
+© 2024 Lady [@ Lady’s Computer]
+
+This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+-->
+<transform
+       xmlns="http://www.w3.org/1999/XSL/Transform"
+       xmlns:catalog="urn:oasis:names:tc:entity:xmlns:xml:catalog"
+       xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
+       version="1.0"
+>
+       <template match="/">
+               <for-each select="//catalog:uri[starts-with(@name, 'about:shushe?source=')]">
+                       <choose>
+                               <when test="substring-after(@uri, '#')='xml'">
+                                       <variable name="destination" select="document(substring-before(@uri, '#'), .)/*/@书社:destination"/>
+                                       <value-of select="@name"/>
+                                       <text>|</text>
+                                       <choose>
+                                               <when test="$destination">
+                                                       <value-of select="$destination"/>
+                                               </when>
+                                               <otherwise>
+                                                       <value-of select="substring-after(@name, 'about:shushe?source=')"/>
+                                               </otherwise>
+                                       </choose>
+                                       <text>&#xA;</text>
+                               </when>
+                               <otherwise>
+                                       <value-of select="@name"/>
+                                       <text>|</text>
+                                       <value-of select="substring-after(@name, 'about:shushe?source=')"/>
+                                       <text>&#xA;</text>
+                               </otherwise>
+                       </choose>
+               </for-each>
+       </template>
+       <output method="text" encoding="UTF-8"/>
+</transform>
index 3339062968fce1faf72cc637f903f6bbdeb2c1c5..2be92185f5e4b25f57ba822f2d96805b1a81ccc5 100644 (file)
@@ -58,7 +58,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        </xslt:otherwise>
                                </xslt:choose>
                        </xslt:template>
-                       <xslt:template match="/*/*//@书社:disable-output-wrapping" priority="0"/>
+                       <xslt:template match="/*/*//@书社:disable-output-wrapping|//@书社:destination" priority="0"/>
                        <xslt:template match="@*|node()" priority="-1">
                                <xslt:copy>
                                        <xslt:apply-templates select="@*|node()"/>
This page took 0.427873 seconds and 4 git commands to generate.