From c36b99b6f8b501b25972f7133c85a29e0f570538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20L=20F=20S=20Bacci?= Date: Thu, 6 Aug 2026 15:23:56 -0300 Subject: [PATCH 1/4] Minimize DTD subsystem --- configure.php | 81 ++++++++++++++++----------------------- scripts/file-entities.php | 14 +++---- scripts/text-entities.php | 7 ++-- 3 files changed, 42 insertions(+), 60 deletions(-) diff --git a/configure.php b/configure.php index e244f9b14d..378539c51d 100755 --- a/configure.php +++ b/configure.php @@ -611,73 +611,52 @@ function git_status() function dtd_conf_entities() { - function dtd_pe_body( string $filename = '' ) + function dtd_pe_load( string $name , string $filename ) : string { if ( file_exists( $filename ) ) { $filename = realpain( $filename ); - return "SYSTEM '$filename'"; + $ret = "\n"; + $ret .= "%{$name};\n\n"; + return $ret; } - return "''"; + return ""; } - global $ac; - $lang = $ac["LANG"]; + // After DTD entities are converted to XML, all this can be reduced to: + // $contents .= dtd_pe_load( "text-entities" , __DIR__ . '/temp/text-entities.dtd' ); + // $contents .= dtd_pe_load( "file-entities" , __DIR__ . '/temp/file-entities.dtd' ); - // When all is converted to XML Entities, - // all this can be reduced to: - // $ent1 = dtd_pe_body( __DIR__ . '/temp/text-entities.ent' ); - // $ent2 = dtd_pe_body( __DIR__ . '/temp/file-entities.ent' ); + $base = $GLOBALS['ac']['LANG_BASE_DIR']; + $lang = $GLOBALS['ac']["LANG"]; - $baseEnt1 = dtd_pe_body( __DIR__ . '/entities/global.ent' ); - $baseEnt2 = dtd_pe_body( __DIR__ . '/temp/file-entities.ent' ); - $baseEnt3 = dtd_pe_body( __DIR__ . '/temp/entities.ent' ); + $contents = ""; - $base = $ac['LANG_BASE_DIR']; + $contents .= "\n\n"; - $langOne1 = dtd_pe_body( __DIR__ . "/../$base/language-defs.ent" ); - $langOne2 = dtd_pe_body( __DIR__ . "/../$base/language-snippets.ent" ); - $langOne3 = dtd_pe_body( __DIR__ . "/../$base/extensions.ent" ); + $contents .= dtd_pe_load( "language-defs" , __DIR__ . "/../$base/language-defs.ent" ); + $contents .= dtd_pe_load( "language-snippets" , __DIR__ . "/../$base/language-snippets.ent" ); + $contents .= dtd_pe_load( "language-extensions" , __DIR__ . "/../$base/extensions.ent" ); - if ( is_single_language() ) + if ( ! is_single_language() ) { - $langTwo1 = dtd_pe_body(); - $langTwo2 = dtd_pe_body(); - $langTwo3 = dtd_pe_body(); + $contents .= dtd_pe_load( "translation-defs" , __DIR__ . "/../$lang/language-defs.ent" ); + $contents .= dtd_pe_load( "translation-snippets" , __DIR__ . "/../$lang/language-snippets.ent" ); + $contents .= dtd_pe_load( "translation-extensions" , __DIR__ . "/../$lang/extensions.ent" ); } - else - { - $langTwo1 = dtd_pe_body( __DIR__ . "/../$lang/language-defs.ent" ); - $langTwo2 = dtd_pe_body( __DIR__ . "/../$lang/language-snippets.ent" ); - $langTwo3 = dtd_pe_body( __DIR__ . "/../$lang/extensions.ent" ); - } - - if ( $ac['CHMENABLED'] == 'yes' ) - $chmpath = dtd_pe_body( __DIR__ . "/chm/manual.chm.xml" ); - else - $chmpath = dtd_pe_body(); - $conf = []; + $contents .= dtd_pe_load( "base-entities" , __DIR__ . '/entities/global.ent' ); + $contents .= dtd_pe_load( "text-entities" , __DIR__ . '/temp/text-entities.dtd' ); + $contents .= dtd_pe_load( "file-entities" , __DIR__ . '/temp/file-entities.dtd' ); - $conf[] = ""; - - $conf[] = ""; - - $conf[] = ""; - $conf[] = ""; - $conf[] = ""; - - $conf[] = ""; - $conf[] = ""; - $conf[] = ""; - - $conf[] = ""; - $conf[] = ""; - $conf[] = ""; + if ( $GLOBALS['ac']['CHMENABLED'] == 'yes' ) + $contents = dtd_pe_body( "manual.chmonly" , __DIR__ . "/chm/manual.chm.xml" ); + else + $contents .= "\n"; $outdir = __DIR__ . "/../$base/temp"; realpain( $outdir , mkdir: true ); - file_put_contents( "{$outdir}/conf.dtd" , implode( "\n" , $conf ) ); + file_put_contents( "{$outdir}/conf.dtd" , $contents ); } function dtd_file_entities() @@ -750,7 +729,11 @@ function dom_load( DOMDocument $dom , string $filename , bool $firstLoad ) : boo { $filename = realpath( $filename ); $options = LIBXML_NOENT | LIBXML_COMPACT | LIBXML_BIGLINES | LIBXML_PARSEHUGE; - return $dom->load( $filename , $options ); + $ret = $dom->load( $filename , $options ); + + $dom->documentElement->setAttribute( 'xml:lang' , $GLOBALS['ac']["LANG"] ); + + return $ret; } function dom_saveload( DOMDocument $dom , string $filename = "" ) : string diff --git a/scripts/file-entities.php b/scripts/file-entities.php index 4e4211cf06..e5fdc3a900 100644 --- a/scripts/file-entities.php +++ b/scripts/file-entities.php @@ -317,23 +317,23 @@ function writeEntities( array $entities ) ksort( $entities ); - $outFile = realpain( __DIR__ . "/../temp/file-entities.ent" , touch: true ); - $lstFile = realpain( __DIR__ . "/../temp/file-entities.txt" , touch: true ); + $dtdFile = realpain( __DIR__ . "/../temp/file-entities.dtd" , touch: true ); + $txtFile = realpain( __DIR__ . "/../temp/file-entities.txt" , touch: true ); $sepPath = realpain( __DIR__ . "/../temp/file-entities" , mkdir: true ); - $singleFile = fopen( $outFile , "w" ); + $singleFile = fopen( $dtdFile , "w" ); if ( ! $singleFile ) { - print "Failed to open $outFile\n."; + print "Failed to open $dtdFile\n."; exit( 1 ); } - fputs( $singleFile , "\n\n" ); + fputs( $singleFile , "\n\n" ); // Life could be simpler, but the building of PHP Manual is already // triping some hardcoded limits of bundled libxml2. // Off loading DTD entities that expand to more DTD entities, - // as external files, somehow avoid these limits. + // as external files, to somehow avoid these limits. if ( LIBXML_LIMITS_HACK ) { @@ -363,7 +363,7 @@ function writeEntities( array $entities ) // entities. $contents = implode( "\n" , array_keys( $entities ) ); - file_put_contents( $lstFile , $contents ); + file_put_contents( $txtFile , $contents ); } function writeEntityIndirectSlow( $singleFile , string $extraFile , string $name , string $text ) diff --git a/scripts/text-entities.php b/scripts/text-entities.php index 05d79cbf4a..75f6bb79ec 100644 --- a/scripts/text-entities.php +++ b/scripts/text-entities.php @@ -12,7 +12,7 @@ +----------------------------------------------------------------------+ | Authors: André L F S Bacci | +----------------------------------------------------------------------+ -| Description: Collect individual entities into an temp/entities.ent. | +| Description: Collect individual entities into an text-entities.dtd. | +----------------------------------------------------------------------+ # Mental model for DTD , @@ -39,7 +39,7 @@ This script collects grouped and individual XML Entity files (detailed below), at some expected relative paths, and generates an -doc-base/temp/entities.ent file with their respective DTD Entities. +doc-base/temp/text-entities.dtd file with their respective DTD Entities. The output file has no duplications, so collection order is important to create some operational semantics. Here, latter loaded entities @@ -175,7 +175,7 @@ public function __construct( class Entities { - private static string $filename = __DIR__ . "/../temp/entities.ent"; + private static string $filename = __DIR__ . "/../temp/text-entities.dtd"; private static array $merged = []; // All EntityData, merged by name, no duplications private static array $unique = []; // Any entity marked unique @@ -425,7 +425,6 @@ function loadEntitySingle( string $path ) function outputFiles( string $filename , array $entities ) { $file = fopen( $filename , "w" ); - fputs( $file , "\n" ); fputs( $file , "\n\n\n" ); $sepFileDir = __DIR__ . "/../temp/text-entities/"; From 527040aab06a677e2581451a9a2d4c39fa3598b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20L=20F=20S=20Bacci?= Date: Thu, 6 Aug 2026 16:45:48 -0300 Subject: [PATCH 2/4] Note the soft exclusion of funcindex.xml --- funcindex.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/funcindex.xml b/funcindex.xml index 9f1e4c9ab9..4e0fdf51b3 100644 --- a/funcindex.xml +++ b/funcindex.xml @@ -1,4 +1,16 @@ + + + &IndexListing; From fb172fbed4ce7fb3f087ba75012d977914bea125 Mon Sep 17 00:00:00 2001 From: alfsb Date: Fri, 7 Aug 2026 10:36:35 -0300 Subject: [PATCH 3/4] Review, Co-authored-by: Louis-Arnaud --- configure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.php b/configure.php index 378539c51d..32e545f87f 100755 --- a/configure.php +++ b/configure.php @@ -650,7 +650,7 @@ function dtd_pe_load( string $name , string $filename ) : string $contents .= dtd_pe_load( "file-entities" , __DIR__ . '/temp/file-entities.dtd' ); if ( $GLOBALS['ac']['CHMENABLED'] == 'yes' ) - $contents = dtd_pe_body( "manual.chmonly" , __DIR__ . "/chm/manual.chm.xml" ); + $contents = dtd_pe_load( "manual.chmonly" , __DIR__ . "/chm/manual.chm.xml" ); else $contents .= "\n"; From 7c13f119d28af7db75263e036160bbd91f3dd373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20L=20F=20S=20Bacci?= Date: Fri, 7 Aug 2026 11:11:50 -0300 Subject: [PATCH 4/4] Fixes, comments, more deprectation notes --- configure.php | 23 +++++++++++------------ manual.xml | 15 +++++++++++++++ scripts/file-entities.php | 5 +++-- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/configure.php b/configure.php index 32e545f87f..20df408d55 100755 --- a/configure.php +++ b/configure.php @@ -630,13 +630,7 @@ function dtd_pe_load( string $name , string $filename ) : string $base = $GLOBALS['ac']['LANG_BASE_DIR']; $lang = $GLOBALS['ac']["LANG"]; - $contents = ""; - - $contents .= "\n\n"; - - $contents .= dtd_pe_load( "language-defs" , __DIR__ . "/../$base/language-defs.ent" ); - $contents .= dtd_pe_load( "language-snippets" , __DIR__ . "/../$base/language-snippets.ent" ); - $contents .= dtd_pe_load( "language-extensions" , __DIR__ . "/../$base/extensions.ent" ); + $contents = "\n\n"; if ( ! is_single_language() ) { @@ -644,19 +638,24 @@ function dtd_pe_load( string $name , string $filename ) : string $contents .= dtd_pe_load( "translation-snippets" , __DIR__ . "/../$lang/language-snippets.ent" ); $contents .= dtd_pe_load( "translation-extensions" , __DIR__ . "/../$lang/extensions.ent" ); } + $contents .= dtd_pe_load( "language-defs" , __DIR__ . "/../$base/language-defs.ent" ); + $contents .= dtd_pe_load( "language-snippets" , __DIR__ . "/../$base/language-snippets.ent" ); + $contents .= dtd_pe_load( "language-extensions" , __DIR__ . "/../$base/extensions.ent" ); $contents .= dtd_pe_load( "base-entities" , __DIR__ . '/entities/global.ent' ); $contents .= dtd_pe_load( "text-entities" , __DIR__ . '/temp/text-entities.dtd' ); $contents .= dtd_pe_load( "file-entities" , __DIR__ . '/temp/file-entities.dtd' ); if ( $GLOBALS['ac']['CHMENABLED'] == 'yes' ) - $contents = dtd_pe_load( "manual.chmonly" , __DIR__ . "/chm/manual.chm.xml" ); + $contents .= dtd_pe_load( "manual.chmonly" , __DIR__ . "/chm/manual.chm.xml" ); else $contents .= "\n"; - $outdir = __DIR__ . "/../$base/temp"; - realpain( $outdir , mkdir: true ); - file_put_contents( "{$outdir}/conf.dtd" , $contents ); + $langTempDir = __DIR__ . "/../$base/temp"; + realpain( $langTempDir , mkdir: true ); + + file_put_contents( __DIR__ . "/temp/lang" , $lang ); + file_put_contents( "{$langTempDir}/conf.dtd" , $contents ); } function dtd_file_entities() @@ -905,7 +904,7 @@ function xinclude_run_xpointer( DOMDocument $dom ) : int function xinclude_residual_fixup( DOMDocument $dom ) { - // XInclude failures are soft errors on translations, so we replace + // XInclude failures are soft errors on translations, so we erase // residual XInclude tags on translations to keep them validating. $fixups = 0; diff --git a/manual.xml b/manual.xml index 42ce09da9d..cae7b040b5 100644 --- a/manual.xml +++ b/manual.xml @@ -1,4 +1,19 @@ + + + +This file is now being ignored, after third-party manual split. +Yet, it is mentioned by name in configure.php, on PhD related +code paths. + +After these code paths are updated or moved into PhD, this can +be deleted. + +Keep these comments outside SGML comment tags, as to make this +file invalid for XML loading. + + + diff --git a/scripts/file-entities.php b/scripts/file-entities.php index e5fdc3a900..a0b5a47da7 100644 --- a/scripts/file-entities.php +++ b/scripts/file-entities.php @@ -29,8 +29,9 @@ - doc-base/temp/file-entites.ent - doc-base/temp/file-entites/dir.dir.ent -The file entity for directories (file listings) are keep as individual -files, to avoid these libxml errors, in some OS/versions: +The file entity for directory listings is kept as an separate files, +instead of a monolithic one, to avoid these libxml errors, in some +OS and/or libxml versions: - Detected an entity reference loop [1] - Maximum entity amplification factor exceeded [2]