git: 9df302ae6942 - main - textproc/xmlstarlet: Improve port and fix build with libxml2 2.14

From: Daniel Engberg <diizzy_at_FreeBSD.org>
Date: Sat, 21 Jun 2025 14:47:46 UTC
The branch main has been updated by diizzy:

URL: https://cgit.FreeBSD.org/ports/commit/?id=9df302ae6942058c37f40d9cbe51b15442273b5e

commit 9df302ae6942058c37f40d9cbe51b15442273b5e
Author:     Daniel Engberg <diizzy@FreeBSD.org>
AuthorDate: 2025-06-21 14:31:27 +0000
Commit:     Daniel Engberg <diizzy@FreeBSD.org>
CommitDate: 2025-06-21 14:46:56 +0000

    textproc/xmlstarlet: Improve port and fix build with libxml2 2.14
    
    * Switch from PORTVERSION to DISTVERSION as recommended by Porters Handbook
    * Import patches from Debian for various fixes [1]
    * Import patch from Gentoo to fix build with new versions of libxml2 and libxslt [2]
    * Remove GNU_CONFIGURE_MANPREFIX
    * Rework Makefile for better readability and to follow Porters Handbook more closely
    * Unbreak with libxml2 2.14 [3]
    
    References:
    
    [1]
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/50-fix-format-security.patch/
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/60-avoid-silent-rules.patch/
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/70-remove-link-usr-lib.patch/
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/80-fix-unesc-dquot.patch/
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/90-fix-upstream-version.patch/
    https://sources.debian.org/patches/xmlstarlet/1.6.1-4/pkg-config.patch/
    
    [2]
    https://gitweb.gentoo.org/repo/gentoo.git/tree/app-text/xmlstarlet/files/xmlstarlet-1.6.1-clang17.patch
    
    [3]
    https://gitlab.archlinux.org/archlinux/packaging/packages/xmlstarlet/-/blob/34eb3ee24a6088a13d5de01af7a2f4e784cff0fc/PKGBUILD#L22
    
    PR:             279976
    Tested by:      George Mitchell <george@m5p.com>
    Approved by:    maintainer timeout, 3 weeks
---
 textproc/xmlstarlet/Makefile                       |  32 +-
 textproc/xmlstarlet/files/patch-clang17-compat     |  59 ++++
 .../files/patch-configure-no-silent-rules          |  16 +
 .../files/patch-configure-remove-libdir-links      |  22 ++
 .../xmlstarlet/files/patch-fix-format-security     | 393 +++++++++++++++++++++
 textproc/xmlstarlet/files/patch-fix-unesc-dqout    |  16 +
 textproc/xmlstarlet/files/patch-fix-version-info   |  47 +++
 textproc/xmlstarlet/files/patch-use-pkgconfig      | 105 ++++++
 8 files changed, 679 insertions(+), 11 deletions(-)

diff --git a/textproc/xmlstarlet/Makefile b/textproc/xmlstarlet/Makefile
index 94426a1ca5b3..8f540ce005b0 100644
--- a/textproc/xmlstarlet/Makefile
+++ b/textproc/xmlstarlet/Makefile
@@ -1,8 +1,8 @@
 PORTNAME=	xmlstarlet
-PORTVERSION=	1.6.1
+DISTVERSION=	1.6.1
 PORTREVISION=	4
 CATEGORIES=	textproc
-MASTER_SITES=	SF/xmlstar/${PORTNAME}/${PORTVERSION}
+MASTER_SITES=	SF/xmlstar/${PORTNAME}/${DISTVERSION}
 
 MAINTAINER=	hrs@FreeBSD.org
 COMMENT=	Command Line XML Toolkit
@@ -11,24 +11,34 @@ WWW=		https://xmlstar.sourceforge.net/
 LICENSE=	MIT
 LICENSE_FILE=	${WRKSRC}/COPYING
 
-USE_GNOME=	libxslt
-USES=		gnome iconv
+USES=		autoreconf gnome iconv pkgconfig
+USE_GNOME=	libxml2 libxslt
+
 GNU_CONFIGURE=	yes
-GNU_CONFIGURE_MANPREFIX=${PREFIX}/share
-CONFIGURE_ARGS=	--with-libxml-prefix=${LOCALBASE} \
-		--with-libxslt-prefix=${LOCALBASE} \
-		${ICONV_CONFIGURE_ARG} \
-		--disable-static-libs
-PLIST_FILES=	bin/xml share/man/man1/xmlstarlet.1.gz
+
+CFLAGS+=	-Wno-incompatible-function-pointer-types
+
+PLIST_FILES=	bin/xml \
+		share/man/man1/xmlstarlet.1.gz
+
 PORTDOCS=	xmlstarlet.txt \
 		xmlstarlet-man.xml \
 		xmlstarlet-ug.html xmlstarlet-ug.pdf \
 		xmlstarlet-ug.ps xmlstarlet-ug.xml \
 		html.css
+
+CONFIGURE_ARGS=	${ICONV_CONFIGURE_ARG}
+
 OPTIONS_DEFINE=	DOCS
 
+post-patch:
+	@${REINPLACE_CMD} -e 's|%%DISTVERSION%%|${DISTVERSION}|g' \
+	    ${PATCH_WRKSRC}/configure.ac
+	@${REINPLACE_CMD} -e 's/ATTRIBUTE_UNUSED/__attribute__((unused))/g' \
+	    ${PATCH_WRKSRC}/src/xml_pyx.c
+
 post-install-DOCS-on:
 	${MKDIR} ${STAGEDIR}${DOCSDIR}
-	cd ${WRKSRC}/doc && ${INSTALL_DATA} ${PORTDOCS} ${STAGEDIR}${DOCSDIR}
+	(cd ${WRKSRC}/doc && ${INSTALL_MAN} ${PORTDOCS} ${STAGEDIR}${DOCSDIR})
 
 .include <bsd.port.mk>
diff --git a/textproc/xmlstarlet/files/patch-clang17-compat b/textproc/xmlstarlet/files/patch-clang17-compat
new file mode 100644
index 000000000000..a2fe3760b21a
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-clang17-compat
@@ -0,0 +1,59 @@
+From e1da090da24f5620784daf853eb1353aa164583f Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Wed, 27 Mar 2024 23:25:39 +0100
+Subject: [PATCH] Address -Wincompatible-function-pointer-types for Clang 17
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Also showed with -Werror=incompatible-pointer-types with GCC.
+
+Bug: https://bugs.gentoo.org/927838
+
+Symptom with GCC was:
+> src/xml.c: In function ‘main’:
+> src/xml.c:300:43: error: passing argument 2 of ‘xmlSetStructuredErrorFunc’ from incompatible pointer type [-Werror=incompatible-pointer-types]
+>   300 |     xmlSetStructuredErrorFunc(&errorInfo, reportError);
+>       |                                           ^~~~~~~~~~~
+>       |                                           |
+>       |                                           void (*)(void *, xmlError *) {aka void (*)(void *, struct _xmlError *)}
+> In file included from /usr/include/libxml2/libxml/valid.h:15,
+>                  from /usr/include/libxml2/libxml/parser.h:19,
+>                  from /usr/include/libxml2/libxml/tree.h:17,
+>                  from /usr/include/libxslt/xslt.h:13,
+>                  from src/xml.c:37:
+> /usr/include/libxml2/libxml/xmlerror.h:898:57: note: expected ‘xmlStructuredErrorFunc’ {aka ‘void (*)(void *, const struct _xmlError *)’} but argument is of type ‘void (*)(void *, xmlError *)’ {aka ‘void (*)(void *, struct _xmlError *)’}
+---
+ src/xml.c     | 2 +-
+ src/xmlstar.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/xml.c b/src/xml.c
+index cf47cc2..e6f19c1 100644
+--- src/xml.c
++++ src/xml.c
+@@ -104,7 +104,7 @@ void reportGenericError(void* ctx, const char * msg, ...) {
+ /* by default all errors are reported */
+ static ErrorInfo errorInfo = { NULL, NULL, VERBOSE, CONTINUE };
+ 
+-void reportError(void *ptr, xmlErrorPtr error)
++void reportError(void *ptr, const xmlError *error)
+ {
+     ErrorInfo *errorInfo = (ErrorInfo*) ptr;
+     assert(errorInfo);
+diff --git a/src/xmlstar.h b/src/xmlstar.h
+index 3e1eed3..e8d7177 100644
+--- src/xmlstar.h
++++ src/xmlstar.h
+@@ -32,7 +32,7 @@ typedef struct _errorInfo {
+     ErrorStop stop;
+ } ErrorInfo;
+ 
+-void reportError(void *ptr, xmlErrorPtr error);
++void reportError(void *ptr, const xmlError *error);
+ void suppressErrors(void);
+ 
+ typedef struct _gOptions {
+-- 
+2.44.0
+
diff --git a/textproc/xmlstarlet/files/patch-configure-no-silent-rules b/textproc/xmlstarlet/files/patch-configure-no-silent-rules
new file mode 100644
index 000000000000..facb3d85a7ca
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-configure-no-silent-rules
@@ -0,0 +1,16 @@
+Description: Don't hide the real compiler flags to allow automatic checks for
+             missing (hardening) flags via blhc. It avoids buildd log scanner
+             tag W-compiler-flags-hidden.
+Author: Mònica Ramírez Arceda <monica@debian.org>
+Last-Update: 2013-07-14
+
+--- configure.ac
++++ configure.ac
+@@ -6,7 +6,6 @@
+ AC_REVISION(AC_PACKAGE_VERSION)
+ 
+ AM_INIT_AUTOMAKE([1.11 foreign -Wall subdir-objects no-define std-options parallel-tests color-tests])
+-AM_SILENT_RULES([yes])
+ AM_MAINTAINER_MODE
+ 
+ [LIBXML_REQUIRED_VERSION=2.6.27]
diff --git a/textproc/xmlstarlet/files/patch-configure-remove-libdir-links b/textproc/xmlstarlet/files/patch-configure-remove-libdir-links
new file mode 100644
index 000000000000..725c65727e00
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-configure-remove-libdir-links
@@ -0,0 +1,22 @@
+Description: Remove links from /usr/lib to fix #722870.
+Author: Mònica Ramírez Arceda <monica@debian.org>
+Bug: https://bugs.debian.org/722870
+Last-Update: 2012-10-28
+--- configure.ac
++++ configure.ac
+@@ -56,7 +56,6 @@
+ AS_IF([test "x$STATIC_LIBS" != xno],
+       [LIBXML_LIBS="$LIBXML_LIBDIR/libxml2.a"],
+       [LIBXML_LIBS="-lxml2"])
+-[LIBXML_LDFLAGS="-L$LIBXML_LIBDIR"]
+ 
+ 
+ XSTAR_LIB_CHECK([LIBXSLT], [xslt-config])
+@@ -68,7 +67,6 @@
+        AS_IF([test "x$STATIC_LIBS" != xno],
+              [LIBXSLT_LIBS="$LIBXSLT_SRCDIR/libexslt/.libs/libexslt.a $LIBXSLT_SRCDIR/libxslt/.libs/libxslt.a"])],
+       [XSLTPROC_PATH="$PATH"
+-       LIBXSLT_LDFLAGS="-L$LIBXSLT_LIBDIR"
+       AS_IF([test "x$STATIC_LIBS" != xno],
+              [LIBXSLT_LIBS="$LIBXSLT_LIBDIR/libexslt.a $LIBXSLT_LIBDIR/libxslt.a"])])
+ 
diff --git a/textproc/xmlstarlet/files/patch-fix-format-security b/textproc/xmlstarlet/files/patch-fix-format-security
new file mode 100644
index 000000000000..7ebfcaa8433e
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-fix-format-security
@@ -0,0 +1,393 @@
+Description: Fix format string literals and avoid gcc error: 
+             "format not a string literal and no format arguments 
+             [-Werror=format-security]"
+Author: Mònica Ramírez Arceda <monica@debian.org>
+Last-Update: 2014-09-10
+
+--- src/xml_elem.c
++++ src/xml_elem.c
+@@ -132,7 +132,7 @@
+             if (xmlTextReaderHasAttributes(reader))
+             {
+                 int have_attr, first = 1;
+-                fprintf(stdout, "[");
++                fprintf(stdout, "%s", "[");
+                 for (have_attr = xmlTextReaderMoveToFirstAttribute(reader);
+                      have_attr;
+                      have_attr = xmlTextReaderMoveToNextAttribute(reader))
+@@ -141,15 +141,15 @@
+                         *avalue = xmlTextReaderConstValue(reader);
+                     char quote;
+                     if (!first)
+-                        fprintf(stdout, " and ");
++                        fprintf(stdout, "%s", " and ");
+                     first = 0;
+ 
+                     quote = xmlStrchr(avalue, '\'')? '"' : '\'';
+                     fprintf(stdout, "@%s=%c%s%c", aname, quote, avalue, quote);
+                 }
+-                fprintf(stdout, "]");
++                fprintf(stdout, "%s", "]");
+             }
+-            fprintf(stdout, "\n");
++            fprintf(stdout, "%s", "\n");
+         }
+         else if (elOps.sort_uniq)
+         {
+--- src/xml.c
++++ src/xml.c
+@@ -145,7 +145,7 @@
+                 fprintf(stderr, ", %s", error->str3);
+             }
+         }
+-        fprintf(stderr, "\n");
++        fprintf(stderr, "%s", "\n");
+ 
+ 
+         if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
+@@ -168,7 +168,7 @@
+ }
+ 
+ #define CHECK_MEM(ret) if (!ret) \
+-        (fprintf(stderr, "out of memory\n"), exit(EXIT_INTERNAL_ERROR))
++        (fprintf(stderr, "%s", "out of memory\n"), exit(EXIT_INTERNAL_ERROR))
+ 
+ void*
+ xmalloc(size_t size)
+@@ -444,7 +444,7 @@
+ 
+         if (*plen >= MAX_NS_ARGS)
+         {
+-            fprintf(stderr, "too many namespaces increase MAX_NS_ARGS\n");
++            fprintf(stderr, "%s", "too many namespaces increase MAX_NS_ARGS\n");
+             exit(EXIT_BAD_ARGS);
+         }
+ 
+--- src/xml_trans.c
++++ src/xml_trans.c
+@@ -168,7 +168,7 @@
+ 
+                 if (*plen >= MAX_PARAMETERS)
+                 {
+-                    fprintf(stderr, "too many params increase MAX_PARAMETERS\n");
++                    fprintf(stderr, "%s", "too many params increase MAX_PARAMETERS\n");
+                     exit(EXIT_INTERNAL_ERROR);
+                 }
+ 
+@@ -197,7 +197,7 @@
+                 {
+                     if (xmlStrchr(string, '\''))
+                     {
+-                        fprintf(stderr,
++                        fprintf(stderr, "%s",
+                             "string parameter contains both quote and double-quotes\n");
+                         exit(EXIT_INTERNAL_ERROR);
+                     }
+@@ -214,7 +214,7 @@
+ 
+                 if (*plen >= MAX_PARAMETERS)
+                 {
+-                    fprintf(stderr, "too many params increase MAX_PARAMETERS\n");
++                    fprintf(stderr, "%s", "too many params increase MAX_PARAMETERS\n");
+                     exit(EXIT_INTERNAL_ERROR);
+                 }
+ 
+--- src/xml_edit.c
++++ src/xml_edit.c
+@@ -339,7 +339,7 @@
+         xmlNodePtr node;
+ 
+         if (nodes->nodeTab[i] == (void*) doc && mode != 0) {
+-            fprintf(stderr, "The document node cannot have siblings.\n");
++            fprintf(stderr, "%s", "The document node cannot have siblings.\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+ 
+@@ -382,7 +382,7 @@
+     for (i = 0; i < nodes->nodeNr; i++)
+     {
+         if (nodes->nodeTab[i] == (void*) doc) {
+-            fprintf(stderr, "The document node cannot be renamed.\n");
++            fprintf(stderr, "%s", "The document node cannot be renamed.\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+         xmlNodeSetName(nodes->nodeTab[i], BAD_CAST val);
+@@ -399,12 +399,12 @@
+     for (i = nodes->nodeNr - 1; i >= 0; i--)
+     {
+         if (nodes->nodeTab[i] == (void*) doc) {
+-            fprintf(stderr, "The document node cannot be deleted.\n");
++            fprintf(stderr, "%s", "The document node cannot be deleted.\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+ 
+         if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
+-            fprintf(stderr, "FIXME: can't delete namespace nodes\n");
++            fprintf(stderr, "%s", "FIXME: can't delete namespace nodes\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+         /* delete node */
+@@ -426,12 +426,12 @@
+     for (i = 0; i < nodes->nodeNr; i++)
+     {
+         if (nodes->nodeTab[i] == (void*) doc) {
+-            fprintf(stderr, "The document node cannot be moved.\n");
++            fprintf(stderr, "%s", "The document node cannot be moved.\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+ 
+         if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
+-            fprintf(stderr, "FIXME: can't move namespace nodes\n");
++            fprintf(stderr, "%s", "FIXME: can't move namespace nodes\n");
+             exit(EXIT_INTERNAL_ERROR);
+         }
+         /* move node */
+@@ -501,7 +501,7 @@
+                 if (!res_to
+                     || res_to->type != XPATH_NODESET
+                     || res_to->nodesetval->nodeNr != 1) {
+-                    fprintf(stderr, "move destination is not a single node\n");
++                    fprintf(stderr, "%s", "move destination is not a single node\n");
+                     continue;
+                 }
+                 edMove(doc, nodes, res_to->nodesetval->nodeTab[0]);
+--- src/trans.c
++++ src/trans.c
+@@ -104,7 +104,7 @@
+     {
+         char *catalogs = getenv("SGML_CATALOG_FILES");
+         if (catalogs == NULL)
+-            fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
++            fprintf(stderr, "%s", "Variable $SGML_CATALOG_FILES not set\n");
+         else
+             xmlLoadCatalogs(catalogs);
+     }
+--- src/xml_pyx.c
++++ src/xml_pyx.c
+@@ -82,9 +82,9 @@
+     /* DON'T modify the attributes array, ever. */
+     const xmlChar*** atts = &attributes;
+ 
+-    fprintf(stdout,"(");
++    fprintf(stdout, "%s", "(");
+     print_qname(prefix, localname);
+-    fprintf(stdout, "\n");
++    fprintf(stdout, "%s", "\n");
+ 
+     if (nb_attributes > 1) {
+         atts = calloc(nb_attributes, sizeof(*atts));
+@@ -139,7 +139,7 @@
+ pyxEndElement(void *userData, const xmlChar *localname, const xmlChar *prefix,
+     const xmlChar *URI)
+ {
+-    fprintf(stdout,")");
++    fprintf(stdout, "%s", ")");
+     print_qname(prefix, localname);
+     putchar('\n');
+ }
+@@ -147,7 +147,7 @@
+ void
+ pyxCharacterData(void *userData, const xmlChar *s, int len)
+ {
+-    fprintf(stdout, "-");
++    fprintf(stdout, "%s", "-");
+     SanitizeData(s, len);
+     putchar('\n');
+ }
+@@ -159,7 +159,7 @@
+ {
+     fprintf(stdout,"?%s ",target);
+     SanitizeData(data, xmlStrlen(data));
+-    fprintf(stdout,"\n");
++    fprintf(stdout, "%s", "\n");
+ }
+ 
+ void
+@@ -191,7 +191,7 @@
+                                   const xmlChar *name)
+ {
+     const xmlChar *p = name;
+-    fprintf (stdout, "&");
++    fprintf (stdout, "%s", "&");
+     /* Up to space is the name of the referenced entity */
+     while (*p && (*p != ' ')) {
+         putchar (*p);
+@@ -205,11 +205,11 @@
+ {
+     fprintf(stdout, "D %s PUBLIC", name); /* TODO: re-check */
+     if (ExternalID == NULL)
+-        fprintf(stdout, " ");
++        fprintf(stdout, "%s", " ");
+     else
+         fprintf(stdout, " \"%s\"", ExternalID);
+     if (SystemID == NULL)
+-        fprintf(stdout, "\n");
++        fprintf(stdout, "%s", "\n");
+     else
+         fprintf(stdout, " \"%s\"\n", SystemID);
+ }
+@@ -217,17 +217,17 @@
+ static void
+ pyxCommentHandler(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
+ {
+-    fprintf(stdout,"C");
++    fprintf(stdout, "%s", "C");
+     SanitizeData(value, xmlStrlen(value));
+-    fprintf(stdout,"\n");
++    fprintf(stdout, "%s", "\n");
+ }
+ 
+ static void
+ pyxCdataBlockHandler(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
+ {
+-    fprintf(stdout,"[");
++    fprintf(stdout, "%s", "[");
+     SanitizeData(value, len);
+-    fprintf(stdout,"\n");
++    fprintf(stdout, "%s", "\n");
+ }
+ 
+ static void
+--- src/xml_C14N.c
++++ src/xml_C14N.c
+@@ -84,7 +84,7 @@
+     if(xpath_filename) {
+         xpath = load_xpath_expr(doc, xpath_filename);
+         if(xpath == NULL) {
+-            fprintf(stderr,"Error: unable to evaluate xpath expression\n");
++            fprintf(stderr, "%s", "Error: unable to evaluate xpath expression\n");
+             xmlFreeDoc(doc); 
+             return(EXIT_BAD_FILE);
+         }
+@@ -160,7 +160,7 @@
+         ret = run_c14n(argv[3], 0, 1, (argc > 4) ? argv[4] : NULL, list, nonet);
+         if(list != NULL) xmlFree(list);
+     } else {
+-        fprintf(stderr, "error: bad arguments.\n");
++        fprintf(stderr, "%s", "error: bad arguments.\n");
+         c14nUsage(argv[0], EXIT_BAD_ARGS);
+     }
+ 
+@@ -275,7 +275,7 @@
+ 
+     ctx = xmlXPathNewContext(parent_doc);
+     if(ctx == NULL) {
+-        fprintf(stderr,"Error: unable to create new context\n");
++        fprintf(stderr, "%s", "Error: unable to create new context\n");
+         xmlFree(expr); 
+         xmlFreeDoc(doc); 
+         return(NULL);
+@@ -301,7 +301,7 @@
+      */
+     xpath = xmlXPathEvalExpression(expr, ctx);
+     if(xpath == NULL) {
+-        fprintf(stderr,"Error: unable to evaluate xpath expression\n");
++        fprintf(stderr, "%s", "Error: unable to evaluate xpath expression\n");
+             xmlFree(expr); 
+         xmlXPathFreeContext(ctx); 
+         xmlFreeDoc(doc); 
+@@ -323,11 +323,11 @@
+     int i;
+     
+     if(nodes == NULL ){ 
+-        fprintf(stderr, "Error: no nodes set defined\n");
++        fprintf(stderr, "%s", "Error: no nodes set defined\n");
+         return;
+     }
+     
+-    fprintf(stderr, "Nodes Set:\n-----\n");
++    fprintf(stderr, "%s", "Nodes Set:\n-----\n");
+     for(i = 0; i < nodes->nodeNr; ++i) {
+         if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
+             xmlNsPtr ns;
+--- src/xml_escape.c
++++ src/xml_escape.c
+@@ -94,7 +94,7 @@
+     buffer = (xmlChar *)						\
+     		xmlRealloc(buffer, buffer_size * sizeof(xmlChar));	\
+     if (buffer == NULL) {       					\
+-	fprintf(stderr, "growing buffer error");			\
++	fprintf(stderr, "%s", "growing buffer error");			\
+ 	abort();							\
+     }									\
+ }
+@@ -129,7 +129,7 @@
+     buffer_size = 1000;
+     buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
+     if (buffer == NULL) {
+-        fprintf(stderr, "allocating buffer error");
++        fprintf(stderr, "%s", "allocating buffer error");
+         abort();
+     }
+     out = buffer;
+--- src/xml_select.c
++++ src/xml_select.c
+@@ -229,7 +229,7 @@
+             {
+                 if (argv[i + 1][0] == '-')
+                 {
+-                    fprintf(stderr, "-E option requires argument <encoding> ex: (utf-8, unicode...)\n");
++                    fprintf(stderr, "%s", "-E option requires argument <encoding> ex: (utf-8, unicode...)\n");
+                     exit(EXIT_BAD_ARGS);
+                 }
+                 else
+@@ -239,7 +239,7 @@
+             }
+             else
+             {
+-                fprintf(stderr, "-E option requires argument <encoding> ex: (utf-8, unicode...)\n");
++                fprintf(stderr, "%s", "-E option requires argument <encoding> ex: (utf-8, unicode...)\n");
+                 exit(EXIT_BAD_ARGS);
+             }
+ 
+@@ -308,7 +308,7 @@
+     if (strcmp(argv[start], "-t") != 0 &&
+         strcmp(argv[start], "--template") != 0)
+     {
+-        fprintf(stderr, "not at the beginning of template\n");
++        fprintf(stderr, "%s", "not at the beginning of template\n");
+         abort();
+     }
+ 
+@@ -345,7 +345,7 @@
+     found_option:
+         if (newtarg == &OPT_SORT && (targ != &OPT_MATCH && targ != &OPT_SORT))
+         {
+-            fprintf(stderr, "sort(s) must follow match\n");
++            fprintf(stderr, "%s", "sort(s) must follow match\n");
+             exit(EXIT_BAD_ARGS);
+         }
+         else if (newtarg == &OPT_TEMPLATE)
+@@ -363,7 +363,7 @@
+         {
+             node = node->parent;
+             if (node->_private != &OPT_IF) {
+-                fprintf(stderr, "else without if\n");
++                fprintf(stderr, "%s", "else without if\n");
+                 exit(EXIT_BAD_ARGS);
+             }
+         }
+@@ -463,9 +463,9 @@
+ 
+     if (templateEmpty)
+     {
+-        fprintf(stderr, "error in arguments:");
+-        fprintf(stderr, " -t or --template option must be followed by");
+-        fprintf(stderr, " --match or other options\n");
++        fprintf(stderr, "%s", "error in arguments:");
++        fprintf(stderr, "%s", " -t or --template option must be followed by");
++        fprintf(stderr, "%s", " --match or other options\n");
+         exit(EXIT_BAD_ARGS);
+     }
+ 
+@@ -528,8 +528,8 @@
+      */
+     if (t == 0)
+     {
+-        fprintf(stderr, "error in arguments:");
+-        fprintf(stderr, " no -t or --template options found\n");
++        fprintf(stderr, "%s", "error in arguments:");
++        fprintf(stderr, "%s", " no -t or --template options found\n");
+         exit(EXIT_BAD_ARGS);
+     }
+ 
diff --git a/textproc/xmlstarlet/files/patch-fix-unesc-dqout b/textproc/xmlstarlet/files/patch-fix-unesc-dqout
new file mode 100644
index 000000000000..e164f3257e94
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-fix-unesc-dqout
@@ -0,0 +1,16 @@
+Description: unesc fails to handle &quot; and &apos; correctly because it thinks they are too long.
+Author: Norbert Kiesel <nk@iname.com>
+Bug: https://bugs.debian.org/837122
+Last-Update: 2016-09-08
+
+--- src/xml_escape.c
++++ src/xml_escape.c
+@@ -222,7 +222,7 @@
+                 semicolon_off++;
+             }
+             entity_len = semicolon_off - i;
+-            if (entity_len < MAX_ENTITY_NAME) {
++            if (entity_len <= MAX_ENTITY_NAME) {
+                 memcpy(entity, &str[i], entity_len);
+                 entity[entity_len] = '\0';
+                 if (str[semicolon_off] == ';') {
diff --git a/textproc/xmlstarlet/files/patch-fix-version-info b/textproc/xmlstarlet/files/patch-fix-version-info
new file mode 100644
index 000000000000..7fb561299e0c
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-fix-version-info
@@ -0,0 +1,47 @@
+Description: Do not get version from git repository, get upstream version from 
+Debian environment variable.
+Author: Mònica Ramírez Arceda <monica@debian.org>
+Bug: https://bugs.debian.org/850842
+Last-Update: 2017-01-24
+
+--- Makefile.am
++++ Makefile.am
+@@ -7,18 +7,11 @@
+ AM_CFLAGS = -Wall -pedantic
+ endif
+ 
+-GIT_DESCRIBE = git describe --tags --dirty
+-
+ # TODO: figure out why log removal is needed and/or make it completely automatic
+ dist-hook:
+ 	@for log in $(srcdir)/examples/*.log ; do if [ -f "$$log" ] ; then \
+ 	  rm $(srcdir)/examples/*.log ; \
+ 	  echo 'ERROR: log files need to cleaned BEFORE making tarball, try again'; exit 1 ; fi ; done
+-	@ if [ -d .git ] ; then \
+-	    if [ $(VERSION) != `$(GIT_DESCRIBE)` ] ; then \
+-		echo 'ERROR: version mismatch, rerun autoconf -f' ; exit 1 ; fi ; \
+-	    $(SED) 's/\[m4_esyscmd_s(\[$(GIT_DESCRIBE)\])\]/[$(VERSION)]/' \
+-	      $(srcdir)/configure.ac > $(distdir)/configure.ac ; fi
+ 
+ cleantar:
+ 	@(rm -f xmlstarlet*.tar.gz)
+@@ -40,9 +33,7 @@
+ dist-win32: $(distdir)-win32.zip
+ 
+ version.h: VERSION
+-	@if [ -d .git ] ; then \
+-	    VERSION=`$(GIT_DESCRIBE)`; \
+-	else VERSION=$(VERSION) ; fi; \
++	VERSION=$(VERSION) ; \
+ 	NEW_VERSION="#define VERSION \"$$VERSION\""; \
+ 	OLD_VERSION=`cat version.h 2>/dev/null` ; \
+ 	if [ "$$NEW_VERSION" != "$$OLD_VERSION" ] ; then \
+--- configure.ac
++++ configure.ac
+@@ -1,5 +1,5 @@
+ AC_PREREQ([2.62])
+-AC_INIT([XMLStarlet], [m4_esyscmd_s([git describe --tags --dirty])],
++AC_INIT([XMLStarlet], [%%DISTVERSION%%],
+         [http://sourceforge.net/projects/xmlstar/support],
+         [],
+         [http://xmlstar.sourceforge.net/])
diff --git a/textproc/xmlstarlet/files/patch-use-pkgconfig b/textproc/xmlstarlet/files/patch-use-pkgconfig
new file mode 100644
index 000000000000..df55ce8dbf0b
--- /dev/null
+++ b/textproc/xmlstarlet/files/patch-use-pkgconfig
@@ -0,0 +1,105 @@
+Description: Use PKG_CHECK_MODULES to detect libxml2, libxslt and libexslt.
+ Also remove the STATIC_LIBS build option, since Debian doesn't ship static
+ libraries for libxslt or libexslt.
+Author: Hugh McMaster <hugh.mcmaster@outlook.com>
+Bug-Debian: https://bugs.debian.org/948791
+Bug-Debian: https://bugs.debian.org/949513
+Forwarded: no
+Last-Update: 2020-05-31
+
+--- configure.ac
++++ configure.ac
+@@ -11,16 +11,6 @@
+ [LIBXML_REQUIRED_VERSION=2.6.27]
+ [LIBXSLT_REQUIRED_VERSION=1.1.9]
+ 
+-XSTAR_LIB_ARGS_WITH([LIBXML], [with-src])
+-XSTAR_LIB_ARGS_WITH([LIBXSLT], [with-src])
+-XSTAR_LIB_ARGS_WITH([LIBICONV])
+-
+-AC_ARG_ENABLE([static-libs],
+-        [AS_HELP_STRING([--enable-static-libs],
+-                [link statically with libxml2 and lib(e)xslt @<:@default=no@:>@])],
+-        [STATIC_LIBS=$enableval],
+-        [STATIC_LIBS=no])
+-
+ AS_IF([test -r doc/xmlstarlet.1], [LACK_DOCS=no], [LACK_DOCS=yes])
+ 
+ AC_ARG_ENABLE([build_docs],
+@@ -42,33 +32,14 @@
+ AC_ARG_PROGRAM          dnl Transforming Program Names When Installing
+ AC_PROG_SED
+ AC_PROG_AWK
++PKG_PROG_PKG_CONFIG
+ 
+-XSTAR_LIB_CHECK([LIBXML], [xml2-config])
++PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= $LIBXML_REQUIRED_VERSION])
++PKG_CHECK_EXISTS([libexslt],
++  [PKG_CHECK_MODULES([LIBXSLT], [libexslt])],
++  [PKG_CHECK_MODULES([LIBXSLT], [libxslt >= $LIBXSLT_REQUIRED_VERSION])])
+ 
+-AS_IF([test "x$LIBXML_SRCDIR" != x],
+-      [LIBXML_INCDIR="$LIBXML_SRCDIR/include"])
+-[: ${LIBXML_INCDIR="$LIBXML_PREFIX/include/libxml2"}]
+-
+-AS_IF([test "x$STATIC_LIBS" != xno],
+-      [LIBXML_CPPFLAGS="-I$LIBXML_INCDIR -DLIBXML_STATIC"],
+-      [LIBXML_CPPFLAGS="-I$LIBXML_INCDIR"])
+-
+-AS_IF([test "x$STATIC_LIBS" != xno],
+-      [LIBXML_LIBS="$LIBXML_LIBDIR/libxml2.a"],
+-      [LIBXML_LIBS="-lxml2"])
+-
+-
+-XSTAR_LIB_CHECK([LIBXSLT], [xslt-config])
+-
+-AS_IF([test "x$LIBXSLT_SRCDIR" != x],
+-      [XSLTPROC_PATH="$LIBXSLT_SRCDIR/xsltproc:$PATH"
+-       LIBXSLT_INCDIR="$LIBXSLT_SRCDIR"
+-       LIBXSLT_LDFLAGS="-L$LIBXSLT_SRCDIR/libexslt/.libs -L$LIBXSLT_SRCDIR/libxslt/.libs"
+-       AS_IF([test "x$STATIC_LIBS" != xno],
+-             [LIBXSLT_LIBS="$LIBXSLT_SRCDIR/libexslt/.libs/libexslt.a $LIBXSLT_SRCDIR/libxslt/.libs/libxslt.a"])],
+-      [XSLTPROC_PATH="$PATH"
+-      AS_IF([test "x$STATIC_LIBS" != xno],
+-             [LIBXSLT_LIBS="$LIBXSLT_LIBDIR/libexslt.a $LIBXSLT_LIBDIR/libxslt.a"])])
++XSLTPROC_PATH="$PATH"
+ 
+ AS_IF([test x"$enable_build_docs" = xyes],
+       [AC_PATH_PROG(XSLTPROC, xsltproc, [none], [$XSLTPROC_PATH])
+@@ -87,13 +58,8 @@
+ 
+ AM_CONDITIONAL([BUILD_DOCS], [test x"$enable_build_docs" = xyes])
+ 
+-
+-AS_IF([test "x$STATIC_LIBS" = xno],
+-      [LIBXSLT_LIBS="-lexslt -lxslt"])
+-
+-[: ${LIBXSLT_INCDIR="$LIBXSLT_PREFIX/include"}]
+-[LIBXSLT_CPPFLAGS="-I$LIBXSLT_INCDIR"]
+-
++[LIBXML_CPPFLAGS="$LIBXML_CFLAGS"]
++[LIBXSLT_CPPFLAGS="$LIBXSLT_CFLAGS"]
+ 
+ [WIN32_EXTRA_LDFLAGS=]
+ [WIN32_EXTRA_LIBS=]
+@@ -116,20 +82,6 @@
+ # replace the libraries from ./configure
+ [USER_LIBS="$LIBS"]
+ [LIBS=]
+-# shared libraries link to dependant libraries automatically
+-AS_IF([test "x$STATIC_LIBS" != xno],
+-   [AC_SEARCH_LIBS([dlopen], [dl], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([sqrt], [m], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([iconv_open], [iconv], [],
+-    [AC_SEARCH_LIBS([libiconv_open], [iconv], [], [], "$USER_LIBS")], "$USER_LIBS")
+-    AC_SEARCH_LIBS([clock_gettime], [rt], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([deflate], [z], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([gcry_cipher_encrypt], [gcrypt], [], [], "$USER_LIBS")
+-
+-    # Checks for inet libraries:
+-    AC_SEARCH_LIBS([gethostent], [nsl], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([setsockopt], [socket net network], [], [], "$USER_LIBS")
+-    AC_SEARCH_LIBS([connect], [inet], [], [], "$USER_LIBS")])
+ 
+ AC_CHECK_FUNCS_ONCE([lstat stat])
+