Index: /trunk/doc/manual/Config.kmk
===================================================================
--- /trunk/doc/manual/Config.kmk	(revision 68860)
+++ /trunk/doc/manual/Config.kmk	(revision 68860)
@@ -0,0 +1,240 @@
+# $Id$
+## @file
+# kBuild Configuration file for the manual.
+#
+
+#
+# Copyright (C) 2010-2017 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+# VirtualBox OSE distribution, in which case the provisions of the
+# CDDL are applicable instead of those of the GPL.
+#
+# You may elect to license modified versions of this file under the
+# terms and conditions of either the GPL or the CDDL or both.
+#
+
+ifndef VBOX_DOC_MANUAL_CONFIG_KMK_INCLUDED
+VBOX_DOC_MANUAL_CONFIG_KMK_INCLUDED = 1
+
+# Include the top-level configure file.
+ifndef VBOX_ROOT_CONFIG_KMK_INCLUDED
+ include $(PATH_ROOT)/Config.kmk
+endif
+
+
+#
+# Globals.
+#
+
+# Source location.
+VBOX_PATH_MANUAL_SRC     := $(PATH_ROOT)/doc/manual
+# Output location.
+VBOX_PATH_MANUAL_OUTBASE := $(PATH_OBJ)/manual
+
+## List of refentry files (manpages).
+VBOX_MANUAL_XML_REFENTRY_FILES := \
+	man_VBoxManage-debugvm.xml \
+	man_VBoxManage-extpack.xml \
+	man_VBoxManage-unattended.xml
+
+
+# Tool locations.
+ifndef VBOX_OSE
+ # use docbook from our tools directory
+ VBOX_PATH_DOCBOOK        ?= $(PATH_DEVTOOLS)/common/DocBook/v1.69.1
+ VBOX_PATH_DOCBOOK_DTD    ?= $(PATH_DEVTOOLS)/common/docbook-xml/v4.3
+ VBOX_XML_CATALOG         ?= $(VBOX_PATH_MANUAL_OUTBASE)/catalog
+ VBOX_XML_CATALOG_DOCBOOK ?= $(VBOX_PATH_MANUAL_OUTBASE)/docbook
+else
+ # use docbook of the build host
+ VBOX_PATH_DOCBOOK        ?= http://docbook.sourceforge.net/release/xsl/current/
+endif
+
+# xsltproc with the catalog trick if applicable.
+ifdef VBOX_XML_CATALOG
+ VBOX_XSLTPROC_WITH_CAT    = $(REDIRECT) -E "XML_CATALOG_FILES=$(VBOX_XML_CATALOG)" $1 -- \
+ 	$(VBOX_XSLTPROC) --nonet --xinclude $(VBOX_XSLTPROC_OPTS)
+ VBOX_XMLLINT_WITH_CAT     = $(REDIRECT) -E "XML_CATALOG_FILES=$(VBOX_XML_CATALOG)" -- \
+	$(VBOX_XMLLINT) --nonet --xinclude --noout $(VBOX_XMLLINT_OPTS)
+else
+ VBOX_XSLTPROC_WITH_CAT    = $(if $(1), $(REDIRECT) $1 --,) $(VBOX_XSLTPROC) --nonet --xinclude $(VBOX_XSLTPROC_OPTS)
+ VBOX_XMLLINT_WITH_CAT     = $(VBOX_XMLLINT) --nonet --xinclude --noout $(VBOX_XMLLINT_OPTS)
+endif
+
+
+##
+# Non-pattern-rule approach to editing XSLT files.
+# $(evalcall2 def_vbox_replace_paths_in_xslt)
+# @param    1   The XSLT source file (relative to Makefile dir).
+# @param    2   Optional output subdirectory (leading slash).
+define def_vbox_replace_paths_in_xslt
+OTHER_CLEAN += $$(VBOX_PATH_MANUAL_OUTBASE)$2/$(notdir $1)
+$$(VBOX_PATH_MANUAL_OUTBASE)$2/$(notdir $1): $$(VBOX_PATH_MANUAL_SRC)/$1 | $$$$(dir $$$$@)
+	$$(call MSG_L1,Pre-processing $$(<) to $$(@))
+	$$(QUIET)$$(SED) \
+		-e 's|@VBOX_PATH_DOCBOOK@|$$(VBOX_PATH_DOCBOOK)|g' \
+		-e 's|@VBOX_PATH_MANUAL_SRC@|$$(VBOX_PATH_MANUAL_SRC)|g' \
+		-e 's|@VBOX_PATH_MANUAL_OUTBASE@|$$(VBOX_PATH_MANUAL_OUTBASE)|g' \
+		-e 's|@VBOX_PATH_MANUAL_OUT_LANG@|$$(VBOX_PATH_MANUAL_OUTBASE)$2|g' \
+		--output "$$(@)" $$<
+endef
+
+
+##
+# Emits rules for preprocessing refentry sources (applying remarks element),
+# and for producing the actual man pages.
+#
+# $(evalcall2 def_vbox_refentry_to_manpage)
+# @param    1   The output directory.
+# @param    2   The XML file name (no path).
+# @param    3   The XML file with full path.
+define def_vbox_refentry_preprocess_for_manpage
+$(1)/$(2): \
+		$(3) \
+		$$(VBOX_PATH_MANUAL_SRC)/docbook-refentry-to-manpage-preprocessing.xsl \
+		$$(VBOX_XML_CATALOG) $$(VBOX_XML_CATALOG_DOCBOOK) \
+		$$(VBOX_VERSION_STAMP) | $$$$(dir $$$$@)
+	$$(call MSG_TOOL,xsltproc $$(notdir $$(firstword $$(filter %.xsl,$$^))),,$$(firstword $$(filter %.xml,$$^)),$$@)
+	$$(QUIET)$$(RM) -f "$$@"
+	$$(QUIET)$$(call VBOX_XSLTPROC_WITH_CAT) --output $$@ \
+		$$(VBOX_PATH_MANUAL_SRC)/docbook-refentry-to-manpage-preprocessing.xsl $$<
+if defined(VBOX_HAVE_XMLLINT) && "$(USER)" == "bird" # Effing stuff happends on build servers, probably kmk related...
+	$$(VBOX_XMLLINT_WITH_CAT) --dtdvalid $$(VBOX_PATH_DOCBOOK_DTD)/docbookx.dtd $$@
+endif
+endef
+
+##
+# Generate a single header file containing everything (no C file).
+#
+# @param   1   Destination file.
+# @param   2   Full source file path.
+# @param   3	Help infix.
+define def_vbox_single_refentry_to_h
+$(1).ts +| $(1): \
+		$$(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) \
+		$$(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) \
+               $(2) \
+		$$(VBOX_XML_CATALOG) $$(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$$$(dir $$$$@)
+	$$(call MSG_TOOL,xsltproc $$(notdir $$(firstword $$(filter %.xsl,$$^))),,$$(filter %.xml,$$^),$$(patsubst %.ts,%,$$@))
+	$$(QUIET)$$(APPEND) -tn "$$@" \
+		'/* Autogenerated by $$(notdir $$(filter %.xsl,$$^)), do not edit! */' \
+		'' \
+		'#include <iprt/message.h>' \
+		'' \
+               'typedef enum HELP_CMD_$(3)' \
+               '{' \
+               '    HELP_CMD_INVALID = 0,'
+	$$(QUIET)$$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$$@") \
+		--stringparam 'g_sMode' 'cmd' $$(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) $(2)
+	$$(QUIET)$$(APPEND) -n "$$@" \
+		'    HELP_CMD_END' \
+		'} HELP_CMD_VBOXMANAGE;' \
+		''
+	$$(NLTAB)$$(QUIET)$$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$$@") \
+		--stringparam 'g_sMode' 'subcmd' $$(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) $(2)
+	$$(QUIET)$$(APPEND) -n "$$@" \
+		''
+	$$(NLTAB)$$(QUIET)$$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$$@") $$(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) $(2)
+	$$(QUIET)$$(APPEND) -n "$$@" \
+               '' \
+               '/* end of file */'
+	$$(QUIET)$$(CP) --changed -- "$$@" "$$(patsubst %.ts,%,$$@)"
+endef
+
+
+#
+# Make sure we've got a rule to make the output directory.
+#
+BLDDIRS += $(VBOX_PATH_MANUAL_OUTBASE)
+
+
+ifdef VBOX_XML_CATALOG
+ #
+ # To avoid network I/O for fetching DTDs, we generate catalogs mapping the public
+ # entity IDs to local files.  (Obviously, only done when we have local files.)
+ #
+ # Create a catalog file for xsltproc that points to docbook catalog.
+ $(VBOX_XML_CATALOG): $(MAKEFILE_CURRENT) | $$(dir $$@)
+	$(call MSG_L1,Creating catalog $@)
+	$(QUIET)$(APPEND) -tn "$@" \
+		'<?xml version="1.0"?>' \
+		'<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">' \
+		'<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">' \
+		'  <delegatePublic publicIdStartString="-//OASIS/ENTITIES DocBook XML"      catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>' \
+		'  <delegatePublic publicIdStartString="-//OASIS/DTD DocBook XML"           catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>' \
+		'  <delegateSystem systemIdStartString="http://www.oasis-open.org/docbook/" catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>' \
+		'  <delegateURI uriStartString="http://www.oasis-open.org/docbook/"         catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>' \
+		'</catalog>'
+
+ # Create a docbook catalog file for xsltproc that points to the local docbook files.
+ $(VBOX_XML_CATALOG_DOCBOOK): $(MAKEFILE_CURRENT) | $$(dir $$@)
+	$(call MSG_L1,Creating catalog $@)
+	$(QUIET)$(APPEND) -tn "$@" \
+		'<?xml version="1.0"?>' \
+		'<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">' \
+		'<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">' \
+		'  <public publicId="-//OASIS//ELEMENTS DocBook XML Information Pool V4.3//EN"          uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbpoolx.mod"/>' \
+		'  <public publicId="-//OASIS//DTD DocBook XML V4.3//EN"                                uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/docbookx.dtd"/>' \
+		'  <public publicId="-//OASIS//DTD DocBook XML V4.4//EN"                                uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/docbookx.dtd"/>' \
+		'  <public publicId="-//OASIS//ENTITIES DocBook XML Character Entities V4.3//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbcentx.mod"/>' \
+		'  <public publicId="-//OASIS//ENTITIES DocBook XML Notations V4.3//EN"                 uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbnotnx.mod"/>' \
+		'  <public publicId="-//OASIS//ENTITIES DocBook XML Additional General Entities V4.3//EN" uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbgenent.mod"/>' \
+		'  <public publicId="-//OASIS//ELEMENTS DocBook XML Document Hierarchy V4.3//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbhierx.mod"/>' \
+		'  <public publicId="-//OASIS//DTD XML Exchange Table Model 19990315//EN"               uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/soextblx.dtd"/>' \
+		'  <public publicId="-//OASIS//DTD DocBook XML CALS Table Model V4.3//EN"               uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/calstblx.dtd"/>' \
+		'  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.3" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>' \
+		'  <rewriteURI         uriStartString="http://www.oasis-open.org/docbook/xml/4.3" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>' \
+		'  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.4" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>' \
+		'  <rewriteURI         uriStartString="http://www.oasis-open.org/docbook/xml/4.4" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Arrow Relations//EN"   uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsa.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Binary Operators//EN"  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsb.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Delimiters//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsc.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Negated Relations//EN" uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsn.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Ordinary//EN"          uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amso.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Relations//EN"         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsr.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Box and Line Drawing//EN"                  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-box.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Russian Cyrillic//EN"                      uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-cyr1.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Non-Russian Cyrillic//EN"                  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-cyr2.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Diacritical Marks//EN"                     uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-dia.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Greek Letters//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk1.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Monotoniko Greek//EN"                      uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk2.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Greek Symbols//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk3.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Alternative Greek Symbols//EN"             uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk4.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Latin 1//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-lat1.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Added Latin 2//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-lat2.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN"           uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-num.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES Publishing//EN"                            uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-pub.ent"/>' \
+		'  <public publicId="ISO 8879:1986//ENTITIES General Technical//EN"                     uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-tech.ent"/>' \
+		'</catalog>'
+
+endif # VBOX_XML_CATALOG
+
+
+#
+# Generate rules for editing the refentry to C/H style sheets.
+#
+$(evalcall2 def_vbox_replace_paths_in_xslt,docbook-refentry-to-C-help.xsl,)
+VBOX_DOCBOOK_REFENTRY_TO_C_HELP = $(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-C-help.xsl
+
+$(evalcall2 def_vbox_replace_paths_in_xslt,docbook-refentry-to-H-help.xsl,)
+VBOX_DOCBOOK_REFENTRY_TO_H_HELP = $(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-H-help.xsl
+
+#
+# Manual dependency.
+#
+$(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-C-help.xsl: $(VBOX_PATH_MANUAL_SRC)/common-formatcfg.xsl
+
+
+endif # !defined(VBOX_DOC_MANUAL_CONFIG_KMK_INCLUDED)
+
Index: /trunk/doc/manual/Makefile.kmk
===================================================================
--- /trunk/doc/manual/Makefile.kmk	(revision 68859)
+++ /trunk/doc/manual/Makefile.kmk	(revision 68860)
@@ -49,4 +49,8 @@
 include $(KBUILD_PATH)/subheader.kmk
 
+ifndef VBOX_DOC_MANUAL_CONFIG_KMK_INCLUDED
+ include $(PATH_SUB_CURRENT)/Config.kmk
+endif
+
 
 #
@@ -83,30 +87,5 @@
 endif
 
-# Source and output locations.
-VBOX_PATH_MANUAL_SRC     := $(PATH_SUB_CURRENT)
-VBOX_PATH_MANUAL_OUTBASE := $(PATH_TARGET)/manual
-
-# tool locations
-ifndef VBOX_OSE
- # use docbook from our tools directory
- VBOX_PATH_DOCBOOK        ?= $(PATH_DEVTOOLS)/common/DocBook/v1.69.1
- VBOX_PATH_DOCBOOK_DTD    ?= $(PATH_DEVTOOLS)/common/docbook-xml/v4.3
- VBOX_XML_CATALOG         ?= $(VBOX_PATH_MANUAL_OUTBASE)/catalog
- VBOX_XML_CATALOG_DOCBOOK ?= $(VBOX_PATH_MANUAL_OUTBASE)/docbook
-else
- # use docbook of the build host
- VBOX_PATH_DOCBOOK        ?= http://docbook.sourceforge.net/release/xsl/current/
-endif
-
-# xsltproc with the catalog trick if applicable.
-ifdef VBOX_XML_CATALOG
- VBOX_XSLTPROC_WITH_CAT    = $(REDIRECT) -E "XML_CATALOG_FILES=$(VBOX_XML_CATALOG)" $1 -- \
- 	$(VBOX_XSLTPROC) --nonet --xinclude $(VBOX_XSLTPROC_OPTS)
- VBOX_XMLLINT_WITH_CAT     = $(REDIRECT) -E "XML_CATALOG_FILES=$(VBOX_XML_CATALOG)" -- \
-	$(VBOX_XMLLINT) --nonet --xinclude --noout $(VBOX_XMLLINT_OPTS)
-else
- VBOX_XSLTPROC_WITH_CAT    = $(if $(1), $(REDIRECT) $1 --,) $(VBOX_XSLTPROC) --nonet --xinclude $(VBOX_XSLTPROC_OPTS)
- VBOX_XMLLINT_WITH_CAT     = $(VBOX_XMLLINT) --nonet --xinclude --noout $(VBOX_XMLLINT_OPTS)
-endif
+
 
 VBOXMANAGEHELP_PATH       ?= $(PATH_STAGE_BIN)/VBoxManageHelp$(SUFF_EXE)
@@ -145,20 +124,4 @@
 VBOX_DOC_XIDL_SRC_TMP  = $(VBOX_PATH_MANUAL_OUTBASE)/en_US/VirtualBox.xidl.tmp
 
-##
-# Non-pattern-rule approach to editing XSLT files.
-# $(evalcall2 def_vbox_replace_paths_in_xslt)
-# @param    1   The XSLT source file (relative to Makefile dir).
-# @param    2   Optional output subdirectory (leading slash).
-define def_vbox_replace_paths_in_xslt
-OTHER_CLEAN += $$(VBOX_PATH_MANUAL_OUTBASE)$2/$(notdir $1)
-$$(VBOX_PATH_MANUAL_OUTBASE)$2/$(notdir $1): $$(VBOX_PATH_MANUAL_SRC)/$1 | $$$$(dir $$$$@)
-	$$(call MSG_L1,Pre-processing $$(<) to $$(@))
-	$$(QUIET)$$(SED) \
-		-e 's|@VBOX_PATH_DOCBOOK@|$$(VBOX_PATH_DOCBOOK)|g' \
-		-e 's|@VBOX_PATH_MANUAL_SRC@|$$(VBOX_PATH_MANUAL_SRC)|g' \
-		-e 's|@VBOX_PATH_MANUAL_OUTBASE@|$$(VBOX_PATH_MANUAL_OUTBASE)|g' \
-		-e 's|@VBOX_PATH_MANUAL_OUT_LANG@|$$(VBOX_PATH_MANUAL_OUTBASE)$2|g' \
-		--output "$$(@)" $$<
-endef
 
 ##
@@ -189,9 +152,4 @@
 endef
 
-## List of refentry files (manpages).
-VBOX_MANUAL_XML_REFENTRY_FILES = \
-	man_VBoxManage-debugvm.xml \
-	man_VBoxManage-extpack.xml \
-	man_VBoxManage-unattended.xml
 
 
@@ -200,5 +158,5 @@
 #
 
-BLDDIRS += $(VBOX_PATH_MANUAL_OUTBASE) $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/, $(VBOX_MANUAL_LANGUAGES))
+BLDDIRS += $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/, $(VBOX_MANUAL_LANGUAGES))
 
 
@@ -314,4 +272,6 @@
                $(addprefix user_,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \
                $(patsubst man_%,%.1,$(basename $(VBOX_MANUAL_XML_REFENTRY_FILES))) \
+               isomakercmd-man.xml \
+               user_isomakercmd-man.xml \
  		$(VBOX_MANUAL_LATEX_FILES_TARGET) \
 		$(VBOX_MANUAL_PNG_FILES_$(lang)) \
@@ -342,5 +302,4 @@
  	$(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/overview_,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \
  	$(VBOX_PATH_MANUAL_OUTBASE)/user_VBoxManage_CommandsOverview.xml \
- 	$(VBOX_PATH_MANUAL_OUTBASE)/user_AdvancedTopics_VISO_Options.xml \
 	$(foreach f,$(VBOX_MANUAL_ADD_LANGUAGES),$(PATH_STAGE_BIN)/UserManual_$(f).pdf) \
 	$(foreach f,$(VBOX_MANUAL_ADD_LANGUAGES),$(PATH_STAGE_BIN)/VirtualBox_$(f).chm) \
@@ -419,66 +378,4 @@
 
 
-#
-# To avoid network I/O for fetching DTDs, we generate catalogs mapping the public
-# entity IDs to local files.  (Obviously, only done when we have local files.)
-#
-ifdef VBOX_XML_CATALOG
-# Create a catalog file for xsltproc that points to docbook catalog.
-$(VBOX_XML_CATALOG): $(MAKEFILE_CURRENT) | $$(dir $$@)
-	$(call MSG_L1,Creating catalog $@)
-	$(QUIET)$(RM) -f $@.tmp $@
-	$(QUIET)$(APPEND) $@.tmp '<?xml version="1.0"?>'
-	$(QUIET)$(APPEND) $@.tmp '<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">'
-	$(QUIET)$(APPEND) $@.tmp '<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">'
-	$(QUIET)$(APPEND) $@.tmp '  <delegatePublic publicIdStartString="-//OASIS/ENTITIES DocBook XML"      catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <delegatePublic publicIdStartString="-//OASIS/DTD DocBook XML"           catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <delegateSystem systemIdStartString="http://www.oasis-open.org/docbook/" catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <delegateURI uriStartString="http://www.oasis-open.org/docbook/"         catalog="file:///$(VBOX_XML_CATALOG_DOCBOOK)"/>'
-	$(QUIET)$(APPEND) $@.tmp '</catalog>'
-	$(QUIET)$(MV) -f $@.tmp $@
-
-# Create a docbook catalog file for xsltproc that points to the local docbook files.
-$(VBOX_XML_CATALOG_DOCBOOK): $(MAKEFILE_CURRENT) | $$(dir $$@)
-	$(call MSG_L1,Creating catalog $@)
-	$(QUIET)$(RM) -f $@.tmp $@
-	$(QUIET)$(APPEND) $@.tmp '<?xml version="1.0"?>'
-	$(QUIET)$(APPEND) $@.tmp '<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">'
-	$(QUIET)$(APPEND) $@.tmp '<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//ELEMENTS DocBook XML Information Pool V4.3//EN"          uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbpoolx.mod"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//DTD DocBook XML V4.3//EN"                                uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/docbookx.dtd"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//DTD DocBook XML V4.4//EN"                                uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/docbookx.dtd"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//ENTITIES DocBook XML Character Entities V4.3//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbcentx.mod"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//ENTITIES DocBook XML Notations V4.3//EN"                 uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbnotnx.mod"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//ENTITIES DocBook XML Additional General Entities V4.3//EN" uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbgenent.mod"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//ELEMENTS DocBook XML Document Hierarchy V4.3//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/dbhierx.mod"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//DTD XML Exchange Table Model 19990315//EN"               uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/soextblx.dtd"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="-//OASIS//DTD DocBook XML CALS Table Model V4.3//EN"               uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/calstblx.dtd"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.3" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <rewriteURI         uriStartString="http://www.oasis-open.org/docbook/xml/4.3" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.4" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <rewriteURI         uriStartString="http://www.oasis-open.org/docbook/xml/4.4" rewritePrefix="file:///$(VBOX_PATH_DOCBOOK_DTD)"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Arrow Relations//EN"   uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsa.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Binary Operators//EN"  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsb.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Delimiters//EN"        uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsc.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Negated Relations//EN" uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsn.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Ordinary//EN"          uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amso.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Math Symbols: Relations//EN"         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-amsr.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Box and Line Drawing//EN"                  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-box.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Russian Cyrillic//EN"                      uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-cyr1.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Non-Russian Cyrillic//EN"                  uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-cyr2.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Diacritical Marks//EN"                     uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-dia.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Greek Letters//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk1.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Monotoniko Greek//EN"                      uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk2.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Greek Symbols//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk3.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Alternative Greek Symbols//EN"             uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-grk4.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Latin 1//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-lat1.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Added Latin 2//EN"                         uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-lat2.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN"           uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-num.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES Publishing//EN"                            uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-pub.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '  <public publicId="ISO 8879:1986//ENTITIES General Technical//EN"                     uri="file:///$(VBOX_PATH_DOCBOOK_DTD)/ent/iso-tech.ent"/>'
-	$(QUIET)$(APPEND) $@.tmp '</catalog>'
-	$(QUIET)$(MV) -f $@.tmp $@
-endif
-
 
 if defined(VBOX_WITH_DOCS) && (!defined(VBOX_ONLY_BUILD) || defined(VBOX_ONLY_DOCS) || defined(VBOX_ONLY_SDK))
@@ -520,6 +417,9 @@
 	$$(addprefix $$(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/user_,$$(filter man_VBoxManage%,$$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
 	$$(addprefix $$(VBOX_PATH_MANUAL_OUTBASE)/overview_,$$(filter man_VBoxManage%,$$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
-	$(VBOX_PATH_MANUAL_OUTBASE)/user_VBoxManage_CommandsOverview.xml \
-	$(VBOX_PATH_MANUAL_OUTBASE)/user_AdvancedTopics_VISO_Options.xml ))
+	$(VBOX_PATH_MANUAL_OUTBASE)/user_VBoxManage_CommandsOverview.xml ))
+
+# Manual dependency for user_AdvancedTopics.xml.
+$(foreach lang,$(VBOX_MANUAL_LANGUAGES) \
+,$(eval $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/user_AdvancedTopics.xml: $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/user_isomakercmd-man.xml))
 
 # Intermediate step to do some variable replacement in the document.
@@ -530,9 +430,9 @@
 # Morph man pages into manual sections.
 # $(evalcall2 def_vbox_refentry_to_user_sect1)
-# @param    1   The XSLT source file (relative to Makefile dir).
-# @param    2   Optional output subdirectory.
+# @param    1  Language.
+# @param    2  the refentry xml base file name.
+# @param    3  the full refentry xml file path.
 define def_vbox_refentry_to_user_sect1
-$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/user_$(2): \
-		$$(VBOX_PATH_MANUAL_SRC)/$(1)/$(2) \
+$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/user_$(2): $(3) \
 		$$(VBOX_PATH_MANUAL_SRC)/docbook-refentry-to-manual-sect1.xsl \
 		$$(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) \
@@ -543,5 +443,7 @@
 endef
 $(foreach lang,$(VBOX_MANUAL_LANGUAGES),$(foreach file,$(VBOX_MANUAL_XML_REFENTRY_FILES) \
-, $(evalcall2 def_vbox_refentry_to_user_sect1,$(lang),$(file))))
+, $(evalcall2 def_vbox_refentry_to_user_sect1,$(lang),$(file),$(VBOX_PATH_MANUAL_SRC)/$(lang)/$(file))))
+$(foreach lang,$(VBOX_MANUAL_LANGUAGES) \
+,$(evalcall2 def_vbox_refentry_to_user_sect1,$(lang),isomakercmd-man.xml,$(PATH_ROOT)/src/VBox/Runtime/common/fs/isomakercmd-man.xml))
 
 
@@ -584,29 +486,4 @@
                '</sect1>'
 
-# Generate the VISO option listing.
-$(VBOX_PATH_MANUAL_OUTBASE)/user_AdvancedTopics_VISO_Options.xml: $(VBOX_RTISOMAKER) $(MAKEFILE_CURRENT) | $$(dir $$@)
-	$(call MSG_GENERATE,,$@,)
-	$(QUIET)$(RM) -f $@ $@.dumpopts
-	$(QUIET)$(APPEND) -tn "$@" \
-		'<?xml version="1.0" encoding="UTF-8"?>' \
-               '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">' \
-               '<sect1> <!-- this will be skipped via xpointer in the include. --> '
-	$(QUIET)$(REDIRECT) -wo $@.dumpopts -E 'VBOX_LOG_FLAGS=disabled' -E 'VBOX_LOG_DEST=nofile' \
-		-- $(VBOX_RTISOMAKER) --help
-	$(QUIET)$(SED) \
-		-e ':a' \
-		-e 'N' \
-		-e '$(DOLLAR)!ba' \
-		-e 's/bldRTIsoMaker/RTIsoMaker/' \
-		-e 's/&/\&amp\;/g' \
-		-e 's/</\&lt\;/g' \
-		-e 's/>/\&gt\;/g' \
-		-e 's/\n*$(DOLLAR)/<\/screen>/' \
-		-e 's/^/<screen>/' \
-		--append $@ $@.dumpopts
-	$(QUIET)$(RM) -f $@.dumpopts
-	$(QUIET)$(APPEND) -n "$@" \
-               '</sect1>'
-
 
 
@@ -644,5 +521,5 @@
 ##########################################################################################
 
-$(foreach f,$(VBOX_MANUAL_LANGUAGES),$(VBOX_PATH_MANUAL_OUTBASE)/$f/UserManual.pdf): \
+$(foreach lang,$(VBOX_MANUAL_LANGUAGES),$(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/UserManual.pdf): \
 		$(VBOX_PATH_MANUAL_OUTBASE)/%/UserManual.pdf : \
 		$(VBOX_PATH_MANUAL_OUTBASE)/%/UserManual.tex \
@@ -1029,95 +906,4 @@
 
 
-#
-# VBoxManage built-in help.
-#
-# Note! Generating the stuff here is a bit annoying, but currently the most
-#       practical way I can come up with.
-#
-OTHERS += \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h
-OTHER_CLEAN += \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp.ts \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h.ts
-help-experiment:: \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp \
-	$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h
-
-$(evalcall2 def_vbox_replace_paths_in_xslt,docbook-refentry-to-C-help.xsl,)
-$(evalcall2 def_vbox_replace_paths_in_xslt,docbook-refentry-to-H-help.xsl,)
-
-$(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-C-help.xsl: $(VBOX_PATH_MANUAL_SRC)/common-formatcfg.xsl # manual dependency.
-
-$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp.ts \
-+| $(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.cpp: \
-		$(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-C-help.xsl \
-		$(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/en_US/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
-		$(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
-	$(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
-	$(QUIET)$(APPEND) -tn "$@" \
-		'/* Autogenerated by $<, do not edit! */' \
-		'' \
-		'#include <iprt/types.h>' \
-		'#include "VBoxManageBuiltInHelp.h"' \
-		''
-	$(foreach refentry,$(filter %.xml,$^) \
-	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") $< $(refentry))
-	$(QUIET)$(APPEND) -n "$@" \
-       	'' \
-		'PCREFENTRY     g_apHelpEntries[] = ' \
-		'{'
-	$(foreach refentry,$(filter %.xml,$^) \
-		,$(NLTAB)$(QUIET)$(APPEND) -n "$@" \
-		'    &g_$(subst -,_,$(tolower $(patsubst man_%,%,$(notdir $(basename $(refentry)))))), ')
-	$(QUIET)$(APPEND) -n "$@" \
-		'};' \
-		'const uint32_t g_cHelpEntries = RT_ELEMENTS(g_apHelpEntries);' \
-               ''
-	$(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
-# The above APPEND stuff trigger some kind of problem on some boxes when not split up...
-# update: Fixed in SVN (strcpy -> memmove in new_job(), job.c - r2591). Just need to rebuild all platforms.
-
-$(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h.ts \
-+| $(VBOX_PATH_MANUAL_OUTBASE)/VBoxManageBuiltInHelp.h: \
-		$(VBOX_PATH_MANUAL_OUTBASE)/docbook-refentry-to-H-help.xsl \
-		$(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/en_US/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
-		$(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
-	$(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
-	$(QUIET)$(APPEND) -tn "$@" \
-		'/* Autogenerated by $<, do not edit! */' \
-               '' \
-               '#ifndef ___VBoxManageBuiltInHelp_h___' \
-               '#define ___VBoxManageBuiltInHelp_h___' \
-               '' \
-               '#include <VBox/refentry.h>' \
-               '' \
-               'RT_C_DECLS_BEGIN' \
-               '' \
-               'typedef enum HELP_CMD_VBOXMANAGE' \
-               '{' \
-               '    HELP_CMD_VBOXMANAGE_INVALID = 0,'
-	$(foreach refentry,$(filter %.xml,$^) \
-	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
-		--stringparam 'g_sMode' 'cmd' $< $(refentry))
-	$(QUIET)$(APPEND) -n "$@" \
-		'    HELP_CMD_VBOXMANAGE_END' \
-		'} HELP_CMD_VBOXMANAGE;'
-	$(foreach refentry,$(filter %.xml,$^) \
-	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
-		--stringparam 'g_sMode' 'subcmd' $< $(refentry))
-	$(QUIET)$(APPEND) -n "$@" \
-		'' \
-		'extern PCREFENTRY     g_apHelpEntries[];' \
-		'extern const uint32_t g_cHelpEntries;' \
-		'' \
-               'RT_C_DECLS_END' \
-		'' \
-		'#endif' \
-               ''
-	$(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
-
 
 include $(FILE_KBUILD_SUB_FOOTER)
Index: /trunk/doc/manual/docbook-refentry-to-C-help.xsl
===================================================================
--- /trunk/doc/manual/docbook-refentry-to-C-help.xsl	(revision 68859)
+++ /trunk/doc/manual/docbook-refentry-to-C-help.xsl	(revision 68860)
@@ -78,5 +78,5 @@
     <xsl:text>
 
-static const REFENTRYSTR </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text>_synopsis[] =
+static const RTMSGREFENTRYSTR </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text>_synopsis[] =
 {</xsl:text>
     <xsl:for-each select="./refsynopsisdiv/cmdsynopsis">
@@ -104,5 +104,5 @@
       -->
     <xsl:text>
-static const REFENTRYSTR </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text>_full_help[] =
+static const RTMSGREFENTRYSTR </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text>_full_help[] =
 {</xsl:text>
     <!-- We start by combining the refentry title and the refpurpose into a short description. -->
@@ -118,13 +118,13 @@
         </xsl:call-template>
         <xsl:text>." },
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
 
     <!-- The follows the usage (synopsis) section. -->
     <xsl:text>
-    {   REFENTRYSTR_SCOPE_GLOBAL,
+    {   RTMSGREFENTRYSTR_SCOPE_GLOBAL,
         "Usage" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "=====" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "" },</xsl:text>
         <xsl:apply-templates select="./refsynopsisdiv/node()"/>
@@ -140,7 +140,7 @@
         <xsl:text>
     {   </xsl:text><xsl:call-template name="calc-scope-refsect1"/><xsl:text>, "" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text><xsl:value-of select="$sTitle"/><xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text>
         <xsl:value-of select="substring($g_sUnderlineRefSect1, 1, string-length($sTitle))"/>
@@ -158,10 +158,19 @@
       -->
     <xsl:text>
-static const REFENTRY </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text> =
+static const RTMSGREFENTRY </xsl:text><xsl:value-of select="$sDataBaseSym"/><xsl:text> =
 {
     /* .idInternal = */   HELP_CMD_</xsl:text>
-    <xsl:call-template name="str:to-upper">
-      <xsl:with-param name="text" select="translate(substring-after(@id, '-'), '-', '_')"/>
-    </xsl:call-template>
+    <xsl:choose>
+      <xsl:when test="contains(@id, '-')">
+        <xsl:call-template name="str:to-upper">   <!-- Multi level command. -->
+          <xsl:with-param name="text" select="translate(substring-after(@id, '-'), '-', '_')"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="str:to-upper">   <!-- Simple command. -->
+          <xsl:with-param name="text" select="@id"/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
     <xsl:text>,
     /* .Synopsis   = */   { RT_ELEMENTS(</xsl:text>
@@ -186,5 +195,5 @@
     <xsl:if test="text()"><xsl:message terminate="yes">cmdsynopsis with text is not supported.</xsl:message></xsl:if>
     <xsl:text>
-    {   </xsl:text><xsl:call-template name="calc-scope-cmdsynopsis"/><xsl:text> | REFENTRYSTR_FLAGS_SYNOPSIS,
+    {   </xsl:text><xsl:call-template name="calc-scope-cmdsynopsis"/><xsl:text> | RTMSGREFENTRYSTR_FLAGS_SYNOPSIS,
         "</xsl:text><xsl:call-template name="emit-indentation"/><xsl:apply-templates select="*|@*"/><xsl:text>" },</xsl:text>
   </xsl:template>
@@ -192,5 +201,5 @@
   <xsl:template match="sbr">
     <xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME | REFENTRYSTR_FLAGS_SYNOPSIS,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME | RTMSGREFENTRYSTR_FLAGS_SYNOPSIS,
         "    </xsl:text><xsl:call-template name="emit-indentation"/> <!-- hardcoded in VBoxManageHelp.cpp too -->
   </xsl:template>
@@ -198,5 +207,5 @@
   <xsl:template match="cmdsynopsis/command">
     <xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME | REFENTRYSTR_FLAGS_SYNOPSIS,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME | RTMSGREFENTRYSTR_FLAGS_SYNOPSIS,
         "</xsl:text><xsl:call-template name="emit-indentation"/>
     <xsl:apply-templates select="node()|@*"/>
@@ -275,13 +284,13 @@
     <xsl:text>
     {   </xsl:text><xsl:call-template name="calc-scope-refsect2"/><xsl:text>, "" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text><xsl:call-template name="emit-indentation"/>
     <xsl:value-of select="$sTitle"/>
     <xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text><xsl:call-template name="emit-indentation"/>
     <xsl:value-of select="substring($g_sUnderlineRefSect2, 1, string-length($sTitle))"/>
     <xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
 
     <!-- Format the text in the section -->
@@ -293,5 +302,5 @@
     <xsl:if test="position() != last()">
       <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
     </xsl:if>
   </xsl:template>
@@ -304,5 +313,5 @@
     <xsl:if test="position() != 1 or not(parent::listitem)">
       <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
     </xsl:if>
     <xsl:call-template name="process-mixed"/>
@@ -318,10 +327,10 @@
     </xsl:if>
     <xsl:for-each select="./varlistentry">
-      <xsl:if test="count(*) != 2 or not(term) or not(listitem)">
-        <xsl:message terminate="yes">Expected exactly one term and one listentry member in varlistentry element.</xsl:message>
+      <xsl:if test="not(term) or not(listitem) or count(listitem) > 1">
+        <xsl:message terminate="yes">Expected one or more term members and exactly one listentry member in varlistentry element.</xsl:message>
       </xsl:if>
       <xsl:if test="not(@spacing) or @spacing != 'compact'">
         <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
       </xsl:if>
       <xsl:apply-templates select="*"/>
@@ -361,5 +370,5 @@
     <xsl:if test="position() != 1 and (not(@spacing) or @spacing != 'compact')">
       <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
     </xsl:if>
     <xsl:for-each select="./listitem">
@@ -380,5 +389,5 @@
     <xsl:if test="position() != 1 and @spaceing != 'compact'">
       <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
+    {   RTMSGREFENTRYSTR_SCOPE_SAME, "" },</xsl:text>
     </xsl:if>
     <xsl:apply-templates select="*"/>
@@ -395,5 +404,5 @@
 
     <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text>
 
@@ -426,5 +435,5 @@
     <xsl:if test="substring-after($sText,'&#x0a;')">
       <xsl:text>" },
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text>
       <xsl:call-template name="screen_text_line">
@@ -608,5 +617,5 @@
   <xsl:template name="process-mixed">
     <xsl:text>
-    {   REFENTRYSTR_SCOPE_SAME,
+    {   RTMSGREFENTRYSTR_SCOPE_SAME,
         "</xsl:text><xsl:call-template name="emit-indentation"/>
 
@@ -631,5 +640,17 @@
 
   <xsl:template name="calc-scope-for-refentry">
-    <xsl:call-template name="calc-scope-const-from-id"/>
+    <xsl:text>HELP_SCOPE_</xsl:text>
+    <xsl:choose>
+      <xsl:when test="contains(@id, '-')">          <!-- Multi level command. -->
+        <xsl:call-template name="str:to-upper">
+          <xsl:with-param name="text" select="translate(substring-after(@id, '-'), '-', '_')"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>                               <!-- Single command. -->
+        <xsl:call-template name="str:to-upper">
+          <xsl:with-param name="text" select="@id"/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
   </xsl:template>
 
@@ -638,5 +659,5 @@
     <xsl:choose>
       <xsl:when test="title[text() = 'Description']">
-        <xsl:text>REFENTRYSTR_SCOPE_GLOBAL</xsl:text>
+        <xsl:text>RTMSGREFENTRYSTR_SCOPE_GLOBAL</xsl:text>
       </xsl:when>
       <xsl:when test="@id or remark[@role='help-scope']">
@@ -644,5 +665,5 @@
       </xsl:when>
       <xsl:otherwise>
-        <xsl:text>REFENTRYSTR_SCOPE_GLOBAL</xsl:text>
+        <xsl:text>RTMSGREFENTRYSTR_SCOPE_GLOBAL</xsl:text>
       </xsl:otherwise>
     </xsl:choose>
@@ -656,5 +677,5 @@
       </xsl:when>
       <xsl:otherwise>
-        <xsl:text>REFENTRYSTR_SCOPE_SAME</xsl:text>
+        <xsl:text>RTMSGREFENTRYSTR_SCOPE_SAME</xsl:text>
       </xsl:otherwise>
     </xsl:choose>
@@ -670,5 +691,5 @@
       </xsl:when>
       <xsl:otherwise>
-        <xsl:text>REFENTRYSTR_SCOPE_SAME</xsl:text>
+        <xsl:text>RTMSGREFENTRYSTR_SCOPE_SAME</xsl:text>
       </xsl:otherwise>
     </xsl:choose>
@@ -704,15 +725,30 @@
   <xsl:template name="calc-scope-const-from-id">
     <xsl:param name="sId" select="@id"/>
-    <xsl:variable name="sPrefix" select="concat(substring-before(ancestor::refentry/@id, '-'), '-')"/>
-    <xsl:if test="not(contains($sId, sPrefix))">
-      <xsl:message terminate="yes">Expected sId (<xsl:value-of select="$sId"/>) to contain <xsl:value-of select="$sPrefix"/></xsl:message>
-    </xsl:if>
+    <xsl:param name="sAncestorId" select="ancestor::refentry/@id"/>
     <xsl:text>HELP_SCOPE_</xsl:text>
-    <xsl:call-template name="str:to-upper">
-      <xsl:with-param name="text" select="translate(substring-after($sId, $sPrefix), '-', '_')"/>
-    </xsl:call-template>
-  </xsl:template>
-
-  <!-- Turns a remark into one or more scope constant. -->
+    <xsl:choose>
+      <xsl:when test="not($sAncestorId)">           <!-- Sanity check. -->
+        <xsl:message terminate="yes">error: calc-scope-const-from-id is invoked without an refentry ancestor with a id. <xsl:call-template name="get-node-path"/> </xsl:message>
+      </xsl:when>
+
+      <xsl:when test="contains($sAncestorId, '-')"> <!-- Multi level command. -->
+        <xsl:variable name="sPrefix" select="concat(substring-before($sAncestorId, '-'), '-')"/>
+        <xsl:if test="not(contains($sId, $sPrefix))">
+          <xsl:message terminate="yes">Expected sId (<xsl:value-of select="$sId"/>) to contain <xsl:value-of select="$sPrefix"/></xsl:message>
+        </xsl:if>
+        <xsl:call-template name="str:to-upper">
+          <xsl:with-param name="text" select="translate(substring-after($sId, $sPrefix), '-', '_')"/>
+        </xsl:call-template>
+      </xsl:when>
+
+      <xsl:otherwise>                               <!-- Single command. -->
+        <xsl:call-template name="str:to-upper">
+          <xsl:with-param name="text" select="translate($sId, '-', '_')"/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- Turns a remark into one or more scope constants. -->
   <xsl:template name="calc-scope-consts-from-remark">
     <xsl:param name="sCondition" select="remark/@condition"/>
@@ -723,5 +759,5 @@
     <xsl:choose>
       <xsl:when test="substring-before($sNormalized, ' ') = 'GLOBAL'">
-        <xsl:text>REFENTRYSTR_SCOPE_GLOBAL</xsl:text>
+        <xsl:text>RTMSGREFENTRYSTR_SCOPE_GLOBAL</xsl:text>
       </xsl:when>
       <xsl:otherwise>
@@ -739,5 +775,5 @@
       <xsl:choose>
         <xsl:when test="substring-before($sList, ' ') = 'GLOBAL'">
-          <xsl:text>| REFENTRYSTR_SCOPE_GLOBAL</xsl:text>
+          <xsl:text>| RTMSGREFENTRYSTR_SCOPE_GLOBAL</xsl:text>
         </xsl:when>
         <xsl:otherwise>
Index: /trunk/doc/manual/docbook-refentry-to-H-help.xsl
===================================================================
--- /trunk/doc/manual/docbook-refentry-to-H-help.xsl	(revision 68859)
+++ /trunk/doc/manual/docbook-refentry-to-H-help.xsl	(revision 68860)
@@ -38,8 +38,19 @@
     -->
   <xsl:template match="refentry">
+    <xsl:variable name="RefEntry" select="."/>
+    <xsl:variable name="sRefEntryId" select="@id"/>
     <xsl:variable name="sBaseNm">
-      <xsl:call-template name="str:to-upper">
-        <xsl:with-param name="text" select="translate(substring-after(@id, '-'), '-', '_')"/>
-      </xsl:call-template>
+      <xsl:choose>
+        <xsl:when test="contains($sRefEntryId, '-')">   <!-- Multi level command. -->
+          <xsl:call-template name="str:to-upper">
+            <xsl:with-param name="text" select="translate(substring-after($sRefEntryId, '-'), '-', '_')"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>                                 <!-- Simple command. -->
+          <xsl:call-template name="str:to-upper">
+            <xsl:with-param name="text" select="translate($sRefEntryId, '-', '_')"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
     </xsl:variable>
 
@@ -47,4 +58,5 @@
       <!-- Generate subcommand enums and defines -->
       <xsl:when test="$g_sMode = 'subcmd'">
+        <!-- Start enum type and start off with the refentry id. -->
         <xsl:text>
 enum
@@ -55,5 +67,7 @@
         <xsl:text> RT_BIT_32(HELP_SCOPE_</xsl:text><xsl:value-of select="$sBaseNm"/><xsl:text>_BIT)
         HELP_SCOPE_</xsl:text><xsl:value-of select="$sBaseNm"/><xsl:text>_BIT = 0</xsl:text>
-        <xsl:for-each select="./refsynopsisdiv/cmdsynopsis">
+
+        <!-- Synopsis IDs -->
+        <xsl:for-each select="./refsynopsisdiv/cmdsynopsis[@id != concat('synopsis-', $sRefEntryId)]">
           <xsl:variable name="sSubNm">
             <xsl:text>HELP_SCOPE_</xsl:text>
@@ -64,12 +78,43 @@
           <xsl:text>,
 #define </xsl:text>
-        <xsl:value-of select="$sSubNm"/>
-        <xsl:value-of select="substring('                                               ',1,56 - string-length($sSubNm))"/>
-        <xsl:text> RT_BIT_32(</xsl:text><xsl:value-of select="$sSubNm"/><xsl:text>_BIT)
-        </xsl:text><xsl:value-of select="$sSubNm"/><xsl:text>_BIT</xsl:text>
+          <xsl:value-of select="$sSubNm"/>
+          <xsl:value-of select="substring('                                               ',1,56 - string-length($sSubNm))"/>
+          <xsl:text> RT_BIT_32(</xsl:text><xsl:value-of select="$sSubNm"/><xsl:text>_BIT)
+        </xsl:text>
+          <xsl:value-of select="$sSubNm"/><xsl:text>_BIT</xsl:text>
         </xsl:for-each>
 
+        <!-- Add scoping info for refsect1, refsect2 and refsect3 IDs that aren't part of the synopsis. -->
+        <xsl:for-each select=".//refsect1[@id] | .//refsect2[@id] | .//refsect3[@id]">
+          <xsl:variable name="sThisId" select="@id"/>
+          <xsl:if test="not($RefEntry[@id = $sThisId]) and not($RefEntry/refsynopsisdiv/cmdsynopsis[@id = concat('synopsis-', $sThisId)])">
+            <xsl:variable name="sSubNm">
+              <xsl:text>HELP_SCOPE_</xsl:text>
+              <xsl:choose>
+                <xsl:when test="contains($sRefEntryId, '-')">   <!-- Multi level command. -->
+                  <xsl:call-template name="str:to-upper">
+                    <xsl:with-param name="text" select="translate(substring-after(@id, '-'), '-', '_')"/>
+                  </xsl:call-template>
+                </xsl:when>
+                <xsl:otherwise>                                 <!-- Simple command. -->
+                  <xsl:call-template name="str:to-upper">
+                    <xsl:with-param name="text" select="translate(@id, '-', '_')"/>
+                  </xsl:call-template>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:variable>
+            <xsl:text>,
+#define </xsl:text>
+            <xsl:value-of select="$sSubNm"/>
+            <xsl:value-of select="substring('                                               ',1,56 - string-length($sSubNm))"/>
+            <xsl:text> RT_BIT_32(</xsl:text><xsl:value-of select="$sSubNm"/><xsl:text>_BIT)
+        </xsl:text>
+            <xsl:value-of select="$sSubNm"/><xsl:text>_BIT</xsl:text>
+          </xsl:if>
+        </xsl:for-each>
+
+        <!-- Done - complete the enum. -->
         <xsl:text>,
-    HELP_SCOPE_</xsl:text><xsl:value-of select="$sBaseNm"/><xsl:text>_END
+        HELP_SCOPE_</xsl:text><xsl:value-of select="$sBaseNm"/><xsl:text>_END
 };
 </xsl:text>
Index: /trunk/doc/manual/docbook2latex.xsl
===================================================================
--- /trunk/doc/manual/docbook2latex.xsl	(revision 68859)
+++ /trunk/doc/manual/docbook2latex.xsl	(revision 68860)
@@ -582,9 +582,14 @@
 
   <xsl:template match="varlistentry">
-    <xsl:if test="not(./term) or not(./listitem) or count(*) != 2">
-      <xsl:message terminate="yes">Expected exactly one term and one listitem element in the varlistentry.</xsl:message>
-    </xsl:if>
+    <xsl:if test="not(./term) or not(./listitem) or count(./listitem) != 1">
+      <xsl:message terminate="yes">Expected at least one term and one listitem element in the varlistentry.</xsl:message>
+    </xsl:if>
+    <!-- TODO: Ideally, I'd like to have each term on a new line. didn't find a simple way of doing that... -->
     <xsl:text>&#x0a;&#x0a;\item[</xsl:text>
-    <xsl:apply-templates select="term"/>
+    <xsl:apply-templates select="./term[1]"/>
+    <xsl:for-each select="./term[position() > 1]">
+      <xsl:text>,&#x0a; </xsl:text>
+      <xsl:apply-templates select="."/>
+    </xsl:for-each>
     <xsl:text>] \hfill \\&#x0a;</xsl:text>
     <xsl:apply-templates select="listitem/*"/>
Index: /trunk/doc/manual/en_US/user_AdvancedTopics.xml
===================================================================
--- /trunk/doc/manual/en_US/user_AdvancedTopics.xml	(revision 68859)
+++ /trunk/doc/manual/en_US/user_AdvancedTopics.xml	(revision 68860)
@@ -4362,26 +4362,5 @@
   </sect1>
 
-  <sect1 id="viso">
-    <title>VISO file format</title>
-
-    <para>The VISO files was introduced with VirtualBox 5.2.  They are virtual ISO images,
-    i.e. constructed in memory from a bunch of files on the host.  A VISO is just the
-    recipe describing how to go about this using a syntax vaguely similar to mkisofs and
-    genisoimage.</para>
-
-    <para>One requirement, the VISO file must start with one of the
-    <option>--iprt-iso-maker-file-marker</option> options. Which of the options
-    you use will dicate the quoting and escaping rules used when reading the
-    file.  The option takes the image UUID as an argument.</para>
-
-    <para>The VISO files are treated as UTF-8 and must not contain any byte order
-    marker (BOM).  There is currently no way to comment out lines in a VISO file.</para>
-
-
-     <xi:include href="../user_AdvancedTopics_VISO_Options.xml" xpointer="xpointer(/sect1/*)"
-       xmlns:xi="http://www.w3.org/2001/XInclude" />
-
-
-  </sect1>
+  <xi:include href="user_isomakercmd-man.xml"    xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
 
 </chapter>
Index: /trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk	(revision 68859)
+++ /trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk	(revision 68860)
@@ -18,4 +18,7 @@
 SUB_DEPTH = ../../../..
 include $(KBUILD_PATH)/subheader.kmk
+
+include $(PATH_ROOT)/doc/manual/Config.kmk
+
 
 VBOX_COMMON_VBOXMANAGE_DEFS = \
@@ -61,6 +64,8 @@
  VBoxManage_DEFS      += $(VBOX_COMMON_VBOXMANAGE_DEFS)
  VBoxManage_DEFS.win   = _WIN32_WINNT=0x0500
- VBoxManage_INCS       = $(PATH_TARGET)/manual
- VBoxManage_INTERMEDIATES = $(PATH_TARGET)/manual/VBoxManageBuiltInHelp.h
+ VBoxManage_INCS = \
+ 	$(VBoxManage_0_OUTDIR)
+ VBoxManage_INTERMEDIATES = \
+ 	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h
  VBoxManage_SOURCES    = \
  	VBoxManage.cpp \
@@ -76,5 +81,5 @@
  	$(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
  	VBoxManageHelp.cpp \
-	$(PATH_TARGET)/manual/VBoxManageBuiltInHelp.cpp \
+	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \
  	VBoxManageHostonly.cpp \
  	VBoxManageInfo.cpp \
@@ -109,3 +114,94 @@
 endif
 
+
+#
+# VBoxManage built-in help from XML refentry in doc/manual/en_US/.
+#
+$(call KB_FN_DO_PASS0_ON_TARGET,VBoxManage)
+
+VBoxManage_CLEAN += \
+	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \
+	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \
+	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h \
+	$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \
+       $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)))
+
+
+
+# Preprocess the xml files, applying remarks.
+$(foreach file,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \
+, $(evalcall2 def_vbox_refentry_preprocess_for_manpage,$(VBoxManage_0_OUTDIR),$(file),$(VBOX_PATH_MANUAL_SRC)/en_US/$(file)))
+
+
+# Generate the .cpp file.
+$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \
++| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp: \
+		$(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) \
+		$(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
+		$(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
+	$(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
+	$(QUIET)$(APPEND) -tn "$@" \
+		'/* Autogenerated by $<, do not edit! */' \
+		'' \
+		'#include "VBoxManageBuiltInHelp.h"' \
+		''
+	$(foreach refentry,$(filter %.xml,$^) \
+	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") $< $(refentry))
+	$(QUIET)$(APPEND) -n "$@" \
+       	'' \
+		'PCRTMSGREFENTRY     g_apHelpEntries[] = ' \
+		'{'
+	$(foreach refentry,$(filter %.xml,$^) \
+		,$(NLTAB)$(QUIET)$(APPEND) -n "$@" \
+		'    &g_$(subst -,_,$(tolower $(patsubst man_%,%,$(notdir $(basename $(refentry)))))), ')
+	$(QUIET)$(APPEND) -n "$@" \
+		'};' \
+		'const uint32_t g_cHelpEntries = RT_ELEMENTS(g_apHelpEntries);' \
+               ''
+	$(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
+# The above APPEND stuff trigger some kind of problem on some boxes when not split up...
+# update: Fixed in SVN (strcpy -> memmove in new_job(), job.c - r2591). Just need to rebuild all platforms.
+
+
+$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \
++| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h: \
+		$(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) \
+		$(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
+		$(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
+	$(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
+	$(QUIET)$(APPEND) -tn "$@" \
+		'/* Autogenerated by $<, do not edit! */' \
+               '' \
+               '#ifndef ___VBoxManageBuiltInHelp_h___' \
+               '#define ___VBoxManageBuiltInHelp_h___' \
+               '' \
+               '#include <iprt/message.h>' \
+               '' \
+               'RT_C_DECLS_BEGIN' \
+               '' \
+               'typedef enum HELP_CMD_VBOXMANAGE' \
+               '{' \
+               '    HELP_CMD_VBOXMANAGE_INVALID = 0,'
+	$(foreach refentry,$(filter %.xml,$^) \
+	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
+		--stringparam 'g_sMode' 'cmd' $< $(refentry))
+	$(QUIET)$(APPEND) -n "$@" \
+		'    HELP_CMD_VBOXMANAGE_END' \
+		'} HELP_CMD_VBOXMANAGE;'
+	$(foreach refentry,$(filter %.xml,$^) \
+	,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
+		--stringparam 'g_sMode' 'subcmd' $< $(refentry))
+	$(QUIET)$(APPEND) -n "$@" \
+		'' \
+		'extern PCRTMSGREFENTRY g_apHelpEntries[];' \
+		'extern const uint32_t  g_cHelpEntries;' \
+		'' \
+               'RT_C_DECLS_END' \
+		'' \
+		'#endif' \
+               ''
+	$(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
+
+
 include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 68859)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 68860)
@@ -28,4 +28,5 @@
 #include <iprt/getopt.h>
 #include <iprt/stream.h>
+#include <iprt/message.h>
 
 #include "VBoxManage.h"
@@ -46,5 +47,5 @@
 enum HELP_CMD_VBOXMANAGE    g_enmCurCommand = HELP_CMD_VBOXMANAGE_INVALID;
 /** The scope maskt for the current subcommand. */
-uint64_t                    g_fCurSubcommandScope = REFENTRYSTR_SCOPE_GLOBAL;
+uint64_t                    g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
 /** String of spaces that can be used for indentation.   */
 static const char           g_szSpaces[] = "                                                ";
@@ -61,5 +62,5 @@
     Assert(g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID);
     g_enmCurCommand       = enmCommand;
-    g_fCurSubcommandScope = REFENTRYSTR_SCOPE_GLOBAL;
+    g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
 }
 
@@ -78,206 +79,4 @@
 
 
-
-/**
- * Retruns the width for the given handle.
- *
- * @returns Screen width.
- * @param   pStrm           The stream, g_pStdErr or g_pStdOut.
- */
-static uint32_t getScreenWidth(PRTSTREAM pStrm)
-{
-    static uint32_t s_acch[2] = { 0, 0 };
-    uint32_t        iWhich    = pStrm == g_pStdErr ? 1 : 0;
-    uint32_t        cch       = s_acch[iWhich];
-    if (cch)
-        return cch;
-
-    const char *psz = RTEnvGet("VBOXMANAGE_SCREEN_WIDTH");
-    if (   !psz
-        || RTStrToUInt32Full(psz, 0, &cch) != VINF_SUCCESS
-        || cch == 0)
-    {
-        int rc = RTStrmQueryTerminalWidth(pStrm, &cch);
-        if (rc == VERR_INVALID_FUNCTION)
-        {
-            /* It's not a console, but in case we're being piped to less/more/list
-               we look for a console handle on the other standard output handle
-               and standard input.  (Latter doesn't work on windows.)  */
-            rc = RTStrmQueryTerminalWidth(pStrm == g_pStdErr ? g_pStdOut : g_pStdErr, &cch);
-            if (rc == VERR_INVALID_FUNCTION || rc == VERR_INVALID_HANDLE)
-                rc = RTStrmQueryTerminalWidth(g_pStdIn, &cch);
-            if (RT_FAILURE(rc))
-                cch = 80;
-        }
-    }
-
-    s_acch[iWhich] = cch;
-    return cch;
-}
-
-
-/**
- * Prints a string table string (paragraph), performing non-breaking-space
- * replacement and wrapping.
- *
- * @returns Number of lines written.
- * @param   pStrm           The output stream.
- * @param   psz             The string table string to print.
- * @param   cchMaxWidth     The maximum output width.
- * @param   fFlags          String flags that may affect formatting.
- */
-static uint32_t printString(PRTSTREAM pStrm, const char *psz, uint32_t cchMaxWidth, uint64_t fFlags)
-{
-    uint32_t    cLinesWritten;
-    size_t      cch     = strlen(psz);
-    const char *pszNbsp = strchr(psz, REFENTRY_NBSP);
-
-    /*
-     * No-wrap case is simpler, so handle that separately.
-     */
-    if (cch <= cchMaxWidth)
-    {
-        if (!pszNbsp)
-            RTStrmWrite(pStrm, psz, cch);
-        else
-        {
-            do
-            {
-                RTStrmWrite(pStrm, psz, pszNbsp - psz);
-                RTStrmPutCh(pStrm, ' ');
-                psz = pszNbsp + 1;
-                pszNbsp = strchr(psz, REFENTRY_NBSP);
-            } while (pszNbsp);
-            RTStrmWrite(pStrm, psz, strlen(psz));
-        }
-        RTStrmPutCh(pStrm, '\n');
-        cLinesWritten = 1;
-    }
-    /*
-     * We need to wrap stuff, too bad.
-     */
-    else
-    {
-        /* Figure the paragraph indent level first. */
-        uint32_t cchIndent = 0;
-        while (*psz == ' ')
-            cchIndent++, psz++;
-        Assert(cchIndent + 4 + 1 <= RT_ELEMENTS(g_szSpaces));
-
-        if (cchIndent + 8 >= cchMaxWidth)
-            cchMaxWidth += cchIndent + 8;
-
-        /* Work our way thru the string, line by line. */
-        uint32_t cchHangingIndent = 0;
-        cLinesWritten = 0;
-        do
-        {
-            RTStrmWrite(pStrm, g_szSpaces, cchIndent + cchHangingIndent);
-            size_t  offLine       = cchIndent + cchHangingIndent;
-            bool    fPendingSpace = false;
-            do
-            {
-                const char *pszSpace = strchr(psz, ' ');
-                size_t      cchWord  = pszSpace ? pszSpace - psz : strlen(psz);
-                if (   offLine + cchWord + fPendingSpace > cchMaxWidth
-                    && offLine != cchIndent
-                    && fPendingSpace /* don't stop before first word */)
-                    break;
-
-                pszNbsp = (const char *)memchr(psz, REFENTRY_NBSP, cchWord);
-                while (pszNbsp)
-                {
-                    size_t cchSubWord = pszNbsp - psz;
-                    if (fPendingSpace)
-                        RTStrmPutCh(pStrm, ' ');
-                    RTStrmWrite(pStrm, psz, cchSubWord);
-                    offLine += cchSubWord + fPendingSpace;
-                    psz     += cchSubWord + 1;
-                    cchWord -= cchSubWord + 1;
-                    pszNbsp = (const char *)memchr(psz, REFENTRY_NBSP, cchWord);
-                    fPendingSpace = true;
-                }
-
-                if (fPendingSpace)
-                    RTStrmPutCh(pStrm, ' ');
-                RTStrmWrite(pStrm, psz, cchWord);
-                offLine += cchWord + fPendingSpace;
-                psz      = pszSpace ? pszSpace + 1 : strchr(psz, '\0');
-                fPendingSpace = true;
-            } while (offLine < cchMaxWidth && *psz != '\0');
-            RTStrmPutCh(pStrm, '\n');
-            cLinesWritten++;
-
-            /* Set up hanging indent if relevant. */
-            if (fFlags & REFENTRYSTR_FLAGS_SYNOPSIS)
-                cchHangingIndent = 4;
-        } while (*psz != '\0');
-    }
-    return cLinesWritten;
-}
-
-
-/**
- * Checks if the given string is empty (only spaces).
- * @returns true if empty, false if not.
- * @param   psz                 The string to examine.
- */
-DECLINLINE(bool) isEmptyString(const char *psz)
-{
-    char ch;
-    while ((ch = *psz) == ' ')
-        psz++;
-    return ch == '\0';
-}
-
-
-/**
- * Prints a string table.
- *
- * @returns Current number of pending blank lines.
- * @param   pStrm               The output stream.
- * @param   pStrTab             The string table.
- * @param   fScope              The selection scope.
- * @param   cPendingBlankLines  Pending blank lines from previous string table.
- * @param   pcLinesWritten      Pointer to variable that should be incremented
- *                              by the number of lines written.  Optional.
- */
-static uint32_t printStringTable(PRTSTREAM pStrm, PCREFENTRYSTRTAB pStrTab, uint64_t fScope, uint32_t cPendingBlankLines,
-                                 uint32_t *pcLinesWritten = NULL)
-{
-    uint32_t cLinesWritten = 0;
-    uint32_t cchWidth      = getScreenWidth(pStrm);
-    uint64_t fPrevScope    = fScope;
-    for (uint32_t i = 0; i < pStrTab->cStrings; i++)
-    {
-        uint64_t fCurScope = pStrTab->paStrings[i].fScope;
-        if ((fCurScope & REFENTRYSTR_SCOPE_MASK) == REFENTRYSTR_SCOPE_SAME)
-        {
-            fCurScope &= ~REFENTRYSTR_SCOPE_MASK;
-            fCurScope |= (fPrevScope & REFENTRYSTR_SCOPE_MASK);
-        }
-        if (fCurScope & REFENTRYSTR_SCOPE_MASK & fScope)
-        {
-            const char *psz = pStrTab->paStrings[i].psz;
-            if (psz && !isEmptyString(psz))
-            {
-                while (cPendingBlankLines > 0)
-                {
-                    cPendingBlankLines--;
-                    RTStrmPutCh(pStrm, '\n');
-                    cLinesWritten++;
-                }
-                cLinesWritten += printString(pStrm, psz, cchWidth, fCurScope & REFENTRYSTR_FLAGS_MASK);
-            }
-            else
-                cPendingBlankLines++;
-        }
-        fPrevScope = fCurScope;
-    }
-
-    if (pcLinesWritten)
-        *pcLinesWritten += cLinesWritten;
-    return cPendingBlankLines;
-}
 
 
@@ -298,5 +97,5 @@
     for (uint32_t i = 0; i < g_cHelpEntries; i++)
     {
-        PCREFENTRY pHelp = g_apHelpEntries[i];
+        PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
         if (pHelp->idInternal == (int64_t)enmCommand)
         {
@@ -304,10 +103,10 @@
             if (cFound == 1)
             {
-                if (fSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL)
+                if (fSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL)
                     RTStrmPrintf(pStrm, "Usage - %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
                 else
                     RTStrmPrintf(pStrm, "Usage:\n");
             }
-            cPendingBlankLines = printStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, cPendingBlankLines, &cLinesWritten);
+            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, &cPendingBlankLines, &cLinesWritten);
             if (!cPendingBlankLines)
                 cPendingBlankLines = 1;
@@ -344,10 +143,10 @@
     for (uint32_t i = 0; i < g_cHelpEntries; i++)
     {
-        PCREFENTRY pHelp = g_apHelpEntries[i];
+        PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
         if (   pHelp->idInternal == (int64_t)enmCommand
             || enmCommand == HELP_CMD_VBOXMANAGE_INVALID)
         {
             cFound++;
-            cPendingBlankLines = printStringTable(pStrm, &pHelp->Help, fSubcommandScope, cPendingBlankLines);
+            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Help, fSubcommandScope, &cPendingBlankLines, NULL /*pcLinesWritten*/);
             if (cPendingBlankLines < 2)
                 cPendingBlankLines = 2;
@@ -377,5 +176,5 @@
 {
     Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
-    Assert(g_fCurSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL);
+    Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
 
     return errorSyntax("No subcommand specified");
@@ -394,5 +193,5 @@
 {
     Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
-    Assert(g_fCurSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL);
+    Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
 
     /* check if help was requested. */
@@ -421,5 +220,5 @@
 {
     Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
-    Assert(g_fCurSubcommandScope != REFENTRYSTR_SCOPE_GLOBAL);
+    Assert(g_fCurSubcommandScope != RTMSGREFENTRYSTR_SCOPE_GLOBAL);
 
     /* check if help was requested. */
@@ -1407,9 +1206,11 @@
         for (uint32_t i = 0; i < g_cHelpEntries; i++)
         {
-            PCREFENTRY pHelp = g_apHelpEntries[i];
+            PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
             while (cPendingBlankLines-- > 0)
                 RTStrmPutCh(pStrm, '\n');
             RTStrmPrintf(pStrm, " %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
-            cPendingBlankLines = printStringTable(pStrm, &pHelp->Synopsis, REFENTRYSTR_SCOPE_GLOBAL, 0);
+            cPendingBlankLines = 0;
+            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, RTMSGREFENTRYSTR_SCOPE_GLOBAL,
+                                          &cPendingBlankLines, NULL /*pcLinesWritten*/);
             cPendingBlankLines = RT_MAX(cPendingBlankLines, 1);
         }
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 68859)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 68860)
@@ -474,4 +474,5 @@
 	common/misc/lockvalidator.cpp \
 	common/misc/message.cpp \
+	common/misc/messagerefentry.cpp \
 	common/misc/once.cpp \
 	common/misc/req.cpp \
@@ -1435,4 +1436,34 @@
 
 #
+# Generate RTIsoMaker / VISO help text from the manpage xml.
+#
+IPRT_XML_REFENTRY_FILES = \
+	common/fs/isomakercmd-man.xml
+
+#$(call KB_FN_DO_PASS0_ON_TARGET,RuntimeR3)
+
+BLDDIRS += $(IPRT_OUT_DIR)/man/
+OTHER_CLEAN += \
+	$(addprefix $(IPRT_OUT_DIR)/man/,$(IPRT_XML_REFENTRY_FILES)) \
+	$(addprefix $(IPRT_OUT_DIR)/man/,$(patsubst %.xml,%.h,$(IPRT_XML_REFENTRY_FILES))) \
+	$(addprefix $(IPRT_OUT_DIR)/man/,$(patsubst %.xml,%.h.ts,$(IPRT_XML_REFENTRY_FILES)))
+
+
+include $(PATH_ROOT)/doc/manual/Config.kmk
+
+# Preprocess the xml files, applying remarks.
+$(foreach file,$(IPRT_XML_REFENTRY_FILES) \
+, $(evalcall2 def_vbox_refentry_preprocess_for_manpage,$(IPRT_OUT_DIR)/man,$(notdir $(file)),$(VBOX_PATH_RUNTIME_SRC)/$(file)))
+
+# generate the header and add it as a dependency to the source using it.
+$(evalcall2 def_vbox_single_refentry_to_h,$(IPRT_OUT_DIR)/man/isomakercmd-man.h, $(IPRT_OUT_DIR)/man/isomakercmd-man.xml)
+common/fs/isomakercmd.cpp_DEPS = $(IPRT_OUT_DIR)/man/isomakercmd-man.h
+common/fs/isomakercmd.cpp_INCS = $(IPRT_OUT_DIR)/man/
+
+foobar: $(IPRT_OUT_DIR)/isomakercmd-man.h.ts
+
+
+
+#
 # RuntimeBldProg - Static Runtime for build programs.
 #
Index: /trunk/src/VBox/Runtime/common/fs/isomakercmd-man.xml
===================================================================
--- /trunk/src/VBox/Runtime/common/fs/isomakercmd-man.xml	(revision 68860)
+++ /trunk/src/VBox/Runtime/common/fs/isomakercmd-man.xml	(revision 68860)
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    manpage for RTIsoMaker/VISO
+
+    Copyright (C) 2006-2017 Oracle Corporation
+
+    This file is part of VirtualBox Open Source Edition (OSE), as
+    available from http://www.virtualbox.org. This file is free software;
+    you can redistribute it and/or modify it under the terms of the GNU
+    General Public License (GPL) as published by the Free Software
+    Foundation, in version 2 as it comes in the "COPYING" file of the
+    VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+    hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ -->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<refentry id="rtisomaker" lang="en">
+
+  <refentryinfo>
+    <pubdate>$Date$</pubdate>
+    <title>VISO file format / RTIsoMaker</title>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>RTIsoMaker</refentrytitle>
+    <manvolnum>8</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <!--<refname>VISO</refname>-->
+    <refname>RTIsoMaker</refname>
+    <refpurpose>ISO image maker</refpurpose>
+    <refclass>IPRT</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis id="synopsis-rtisomaker"> <!-- The 'id' is mandatory and must start with 'synopsis-'. -->
+      <command>RTIsoMaker</command>
+      <arg><replaceable>options</replaceable></arg>
+      <arg>@<replaceable>commands.rsp</replaceable></arg>
+      <arg choice="req" rep="repeat"><replaceable>filespec</replaceable></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+    <para>Construct a virtual ISO 9660 / Joliet / UDF / HFS hybrid image and either write it to a
+    file (RTIsoMaker) or serve it as a virtual image (VISO).</para>
+
+    <refsect2 id="rtisomaker-viso">
+      <title>VISO file format</title>
+      <para>A VISO file is a virtual ISO image, i.e. constructed in memory from a bunch of files on
+        the host.  A VISO is just the recipe describing how to go about this using a syntax vaguely
+        similar to mkisofs and genisoimage.</para>
+
+      <para>One requirement is that the VISO file must start with one of the
+        <option>--iprt-iso-maker-file-marker</option> options. Which of the options you use will
+        dictate the quoting and escaping rules used when reading the file.  The option takes the
+        image UUID as an argument.</para>
+
+      <para>The VISO files are treated as UTF-8 and must not contain any byte order marker (BOM).
+        There is currently no way to comment out lines in a VISO file.</para>
+
+    </refsect2>
+
+    <refsect2 id="rtisomaker-filespecs">
+      <title>File specifications and --name-setup</title>
+      <para>All non-options that does not start with '@' are taken to indicate a file, directory,
+        or similar that is should be added to the ISO image.  Directories are added recursively and
+        content is subject to filtering options.</para>
+
+      <para>Since there can be up to six different namespaces on an ISO, it is handy to be able to
+        control the names used in each and be able to exclude an object from one or more namespaces.
+        The <option>--name-setup</option> option specifies the file specification format to use
+        forthwith.</para>
+
+      <para>The default setup is:</para>
+      <!-- indent this: -->
+      <para><computeroutput>    --name-setup iso+joliet+udf+hfs</computeroutput></para>
+
+      <para>Which means you specify one on-ISO name for all namespaces followed by '=' and the
+        source file system name.  Only specifying the source file system will add the
+        file/dir/whatever to the root of the ISO image.</para>
+
+      <para>Lets look at the following two examples:</para>
+
+      <!-- indent these -->
+      <para><computeroutput>    /docs/readme.txt=/home/user/Documents/product-x-readme.txt</computeroutput></para>
+      <para><computeroutput>    /home/user/Documents/product-x-readme.txt</computeroutput></para>
+
+      <para>In the first case the file <computeroutput>'/home/user/Documents/product-x-readme.txt'</computeroutput>
+        is added to the ISO image as <computeroutput>'/docs/readme.txt'</computeroutput> in all
+        enabled namespaces.  In the primary ISO 9660 namespace, the filename will by default be
+        converted to upper case because it's required by the spec.</para>
+
+      <para>In the second case the file is added to the root under the name
+        <computeroutput>'product-x-readme.txt'</computeroutput> in all namespaces. Though, in the
+        primary ISO 9660 namespace the name will be transformed to apply with the current ISO level,
+        probably uppercased, possibly truncated too. </para>
+
+      <para>Given  <option>--name-setup iso,joliet,udf</option>  you can specify the name individually
+        for each of the three namespace, if you like.  If you omit any, they will use last name given.
+        Any names left blank (<computeroutput>==</computeroutput>) will be considered omitted.</para>
+
+      <para>A different name in each namespace:</para>
+      <para><computeroutput>    /ISO.TXT=/Joliet.TxT=/UDF.txt=/tmp/iso/real.txt</computeroutput></para>
+      <para>Specific name in the ISO 9660 namespace, same in the rest:</para>
+      <para><computeroutput>    /ISO.TXT=/OtherNamespaces.TxT=/tmp/iso/real.txt</computeroutput></para>
+      <para>Omit the file from the ISO 9660 namespace:</para>
+      <para><computeroutput>    =/OtherNamespaces.TxT=/tmp/iso/real.txt</computeroutput></para>
+      <para>Omit the file from the joliet namespace:</para>
+      <para><computeroutput>    /ISO.TXT==/UDF.TxT=/tmp/iso/real.txt</computeroutput></para>
+      <para>Use the same filename as the source everywhere:</para>
+      <para><computeroutput>    /tmp/iso/real.txt</computeroutput></para>
+
+
+      <para>Using for instance  <option>--name-setup udf</option>  you can add a files/dirs/whatever
+        to select namespace(s) without the more complicated empty name syntax above.</para>
+
+      <para>When adding directories, you can only control the naming and omitting of the directory
+        itself, not any recursively added files and directories below it.</para>
+
+    </refsect2>
+  </refsect1>
+
+  <refsect1 id="rtisomaker-general-options">
+    <title>Options - General</title>
+
+    <variablelist>
+      <varlistentry>
+        <term><option>-o <replaceable>output-file</replaceable></option></term>
+        <term><option>--output=<replaceable>output-file</replaceable></option></term>
+        <listitem><para>The output filename.  This option is not supported in VISO mode.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--name-setup <replaceable>spec</replaceable></option></term>
+        <listitem><para>Configures active namespaces and how file specifications are to be
+            interpreted.  The specification is a comma separated list.  Each element in the list is
+            a sub-list separated by space, <computeroutput>'+'</computeroutput> or
+            <computeroutput>'|'</computeroutput> giving the namespaces that elements controls.
+            Namespaces are divied into two major and minor ones, you cannot specifying a minor
+            before the major it belongs to.</para>
+         <para>Major namespaces and aliases in parentheses:</para>
+         <itemizedlist>
+           <listitem><para>iso (primary, iso9660, iso-9660, primary-iso, iso-primary)</para></listitem>
+           <listitem><para>joliet</para></listitem>
+           <listitem><para>udf</para></listitem>
+           <listitem><para>hfs (hfs-plus)</para></listitem>
+         </itemizedlist>
+         <para>Minor namespaces:</para>
+         <itemizedlist>
+            <listitem><para>rock:        rock ridge on previous major namespace (iso / joliet)</para></listitem>
+            <listitem><para>iso-rock:    rock ridge extensions on primary ISO 9660 namespace</para></listitem>
+            <listitem><para>joliet-rock: rock ridge on joliet namespace (just for fun)</para></listitem>
+            <listitem><para>trans-tbl:   translation table file on previous major namespace</para></listitem>
+            <listitem><para>iso-trans-tbl</para></listitem>
+            <listitem><para>joliet-trans-tbl</para></listitem>
+            <listitem><para>udf-trans-tbl</para></listitem>
+            <listitem><para>hfs-trans-tbl</para></listitem>
+         </itemizedlist>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+  </refsect1>
+
+</refentry>
+
+
+<!--
+
+
+Options - General:
+
+
+
+    -dashdash-push-iso <iso-file>
+    -dashdash-push-iso-no-joliet <iso-file>
+    -dashdash-push-iso-no-rock <iso-file>
+    -dashdash-push-iso-no-rock-no-joliet <iso-file>
+        Open the specified ISO file and use it as source file system until the
+        corresponding -dashdash-pop options is encountered.  The variations are for
+        selecting which namespace on the ISO to (not) access.  These options
+        are handy for copying files/directories/stuff from an ISO without
+        having to extract them first or using the :iprtvfs: syntax.
+
+    -dashdash-pop
+        Pops a -dashdash-push-iso of the source file system stack.
+
+    -dashdash-import-iso <iso-file>
+        Imports everything on the given ISO file. You can use -dashdash-name-setup to
+        omit namespaces.
+
+
+Options - Namespaces:
+
+    -dashdash-iso-level <0|1|2|3>
+        Sets the ISO level:
+            - 0: Disable primary ISO namespace.
+            - 1: ISO level 1: Filenames 8.3 format and limited to 4GB - 1.
+            - 2: ISO level 2: 31 char long names and limited to 4GB - 1.
+            - 3: ISO level 3: 31 char long names and support for >=4GB files.
+            - 4: Fictive level used by other tools. Not yet implemented.
+        Default: 3
+
+    -dashdash-rock-ridge
+    -dashdash-limited-rock-ridge
+    -dashdash-no-rock-ridge
+        Enables or disables rock ridge support for the primary ISO 9660
+        namespace.  The -dashdash-limited-rock-ridge option omits a couple of bits in
+        the root directory that would make Linux pick rock ridge over joliet.
+        Default: -dashdash-limited-rock-ridge
+    -J
+    -dashdash-joliet
+    -dashdash-no-joliet
+        Enables or disable the joliet namespace.  This option must precede any
+        file specifications.  Default: -dashdash-joliet
+
+    -dashdash-joliet-ucs-level <1|2|3>
+    -dashdash-ucs-level <1|2|3>
+        Set the Joliet UCS support level.  This is currently only flagged in the
+        image but not enforced on the actual path names.  Default level: 3
+
+
+Options - File attributes:
+
+    -dashdash-rational-attribs
+        Enables rational file attribute handling:
+            * Owner ID is set to zero
+            * Group ID is set to zero
+            * Mode is set to 0444 for non-executable files.
+            * Mode is set to 0555 for executable files.
+            * Mode is set to 0555 for directories, preserving stick bits.
+        This is default.
+
+    -dashdash-strict-attribs
+        Counters -dashdash-rational-attribs and causes attributes to be recorded
+        exactly as they appear in the source.
+
+    -dashdash-file-mode <mode>
+    -dashdash-no-file-mode
+        Controls the forced file mode mask for rock ridge, UDF and HFS.
+
+    -dashdash-dir-mode <mode>
+    -dashdash-no-dir-mode
+        Controls the forced directory mode mask for rock ridge, UDF and HFS.
+
+    -dashdash-new-dir-mode <mode>
+        Controls the default mode mask (rock ridge, UDF, HFS) for directories
+        that are created implicitly.  The -dashdash-dir-mode option overrides this.
+
+    -dashdash-chmod <mode>:<on-iso-file>
+       Explictily sets the rock ridge, UDF and HFS file mode for a
+       file/dir/whatever that has already been added to the ISO.  The mode can
+       be octal, a+x, a+r, or a+rx.  (Support for more complicated mode
+       specifications may be implemented at a later point.)
+       Note that only namespaces in the current -dashdash-name-setup are affected.
+
+    -dashdash-chown <owner-id>:<on-iso-file>
+       Explictily sets the rock ridge, UDF and HFS file owner ID (numeric) for a
+       file/dir/whatever that has already been added to the ISO.
+       Note that only namespaces in the current -dashdash-name-setup are affected.
+
+    -dashdash-chgrp <group-id>:<on-iso-file>
+       Explictily sets the rock ridge, UDF and HFS file group ID (numeric) for a
+       file/dir/whatever that has already been added to the ISO.
+       Note that only namespaces in the current -dashdash-name-setup are affected.
+
+
+Options - Booting:
+
+    -dashdash-eltorito-new-entry
+    -dashdash-eltorito-alt-boot
+        Starts a new El Torito boot entry.
+
+    -dashdash-eltorito-add-image <filespec>
+        File specification of a file that should be added to the image and used
+        as the El Torito boot image of the current boot entry.
+
+    -b <on-iso-file>
+    -dashdash-eltorito-boot <on-iso-file>
+        Specifies a file on the ISO as the El Torito boot image for the current
+        boot entry.
+
+    -dashdash-eltorito-floppy-12
+    -dashdash-eltorito-floppy-144
+    -dashdash-eltorito-floppy-288
+    -dashdash-no-emulation-boot
+    -dashdash-hard-disk-boot
+        Sets the boot image emulation type of the current El Torito boot entry.
+
+    -dashdash-boot-load-seg <seg>
+        Specify the image load segment for the current El Torito boot entry.
+        Default: 0x7c0
+
+    -dashdash-boot-load-size <seg>
+        Specify the image load size in emulated sectors for the current El Torito
+        boot entry.  Default: 4 (sectors of 512 bytes)
+
+    -dashdash-no-boot
+        Indicates that the current El Torito boot entry isn't bootable. (The
+        BIOS will allegedly configure the emulation, but not attempt booting.)
+
+    -dashdash-boot-info-table
+        Write a isolinux/syslinux boot info table into the boot image for the
+        current El Torito boot entry.
+
+    -dashdash-eltorito-platform-id <id>
+        Set the El Torito platform ID of the current entry, a new entry of the
+        verification entry depending on when it's used.  The ID must be one
+        of: x86, PPC, Mac, efi
+
+    -c <namespec>
+    -dashdash-boot-catalog <namespec>
+        Enters the El Torito boot catalog into the namespaces as a file.  The
+        'namespec' uses the same format as a 'filespec', but omits the final
+        source file system name component.
+
+    -G <file>
+    -dashdash-generic-boot <file>
+        Specifies a file that should be loaded at offset 0 in the ISO image.
+        The file must not be larger than 32KB.  When creating a hybrid image,
+        parts of this may be regenerated by partition tables and such.
+
+
+Options - String properties (applied to active namespaces only):
+
+    -dashdash-abstract <file-id>
+        The name of the abstract file in the root dir.
+
+    -A <text|_file-id>
+    -dashdash-application-id <text|_file-id>
+        Application ID string or root file name.  The latter must be prefixed
+        with an underscore.
+
+    -dashdash-biblio <file-id>
+        The name of the bibliographic file in the root dir.
+
+    -dashdash-copyright <file-id>
+        The name of the copyright file in the root dir.
+
+    -P <text|_file-id>
+    -dashdash-publisher <text|_file-id>
+        Publisher ID string or root file name.  The latter must be prefixed
+        with an underscore.
+
+    -p <text|_file-id>
+    -dashdash-preparer <text|_file-id>
+        Data preparer ID string or root file name.  The latter must be prefixed
+        with an underscore.
+
+    -dashdash-sysid <text>
+        System ID string.
+
+    -dashdash-volid <text>
+    -dashdash-volume-id <text>
+        Volume ID string (label).  (It is possible to set different labels for
+        primary ISO 9660, joliet, UDF and HFS by changing the active namespaces
+        using the -dashdash-name-setup option between -dashdash-volume-id occurences.)
+
+    -dashdash-volset <text>
+        Volume set ID string.
+
+
+Options - Compatibility:
+
+    -dashdash-graft-points
+        Alias for -dashdash-name-setup iso+joliet+udf+hfs.
+
+    -l
+    -dashdash-long-names
+        Allow 31 charater filenames.  Just ensure ISO level >= 2 here.
+
+    -R
+    -dashdash-rock
+        Same as -dashdash-rock-ridge and -dashdash-strict-attribs.
+
+    -r
+    -dashdash-rational-rock
+        Same as -dashdash-rock-ridge and -dashdash-rational-attribs.
+
+
+Options - VISO specific:
+
+    -dashdash-iprt-iso-maker-file-marker <UUID>
+    -dashdash-iprt-iso-maker-file-marker-bourne <UUID>
+    -dashdash-iprt-iso-maker-file-marker-bourne-sh <UUID>
+        Used as first option in a VISO file to specify the file UUID and that
+        it is formatted using bourne-shell argument quoting & escaping style.
+
+    -dashdash-iprt-iso-maker-file-marker-ms <UUID>
+    -dashdash-iprt-iso-maker-file-marker-ms-sh <UUID>
+        Used as first option in a VISO file to specify the file UUID and that
+        it is formatted using microsoft CRT argument quoting & escaping style.
+
+
+Options - Testing (not applicable to VISO):
+
+    -dashdash-output-buffer-size <bytes>
+        Selects a specific output buffer size for testing virtual image reads.
+
+    -dashdash-random-output-buffer-size
+        Enables randomized buffer size for each virtual image read, using the
+        current output buffer size (-dashdash-output-buffer-size) as maximum.
+
+    -dashdash-random-order-verification <size>
+        Enables verification pass of the image that compares blocks of the given
+        size in random order from the virtual and output images
+
+
+ -->
Index: /trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp	(revision 68859)
+++ /trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp	(revision 68860)
@@ -667,4 +667,6 @@
 };
 
+#include "isomakercmd-man.h"
+
 
 /*********************************************************************************************************************************
@@ -810,4 +812,5 @@
 static void rtFsIsoMakerCmdUsage(PRTFSISOMAKERCMDOPTS pOpts, const char *pszProgName)
 {
+#if 0
     rtFsIsoMakerPrintf(pOpts,
                        "Usage: %s [options] [@commands.rsp] <filespec1> [filespec2 [..]]\n"
@@ -1132,6 +1135,11 @@
                        "\n"
                        , RTPathFilename(pszProgName));
-
-
+#else
+    if (pOpts->pErrInfo)
+        rtFsIsoMakerPrintf(pOpts, "Usage: %s [options] [@commands.rsp] <filespec1> [filespec2 [..]]\n",
+                           RTPathFilename(pszProgName));
+    else
+        RTMsgRefEntryHelp(g_pStdOut, &g_rtisomaker);
+#endif
 }
 
Index: /trunk/src/VBox/Runtime/common/misc/messagerefentry.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/messagerefentry.cpp	(revision 68860)
+++ /trunk/src/VBox/Runtime/common/misc/messagerefentry.cpp	(revision 68860)
@@ -0,0 +1,320 @@
+/* $Id$ */
+/** @file
+ * IPRT - Program usage and help formatting.
+ */
+
+/*
+ * Copyright (C) 2009-2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/message.h>
+
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/env.h>
+#include <iprt/stream.h>
+#include "internal/process.h"
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** Spaces for intending. */
+static const char           g_szSpaces[] = "                                                ";
+
+
+/**
+ * Retruns the width for the given handle.
+ *
+ * @returns Screen width.
+ * @param   pStrm           The stream, g_pStdErr or g_pStdOut.
+ */
+static uint32_t getScreenWidth(PRTSTREAM pStrm)
+{
+    static uint32_t s_acch[2] = { 0, 0 };
+    uint32_t        iWhich    = pStrm == g_pStdErr ? 1 : 0;
+    uint32_t        cch       = s_acch[iWhich];
+    if (cch)
+        return cch;
+
+    const char *psz = RTEnvGet("IPRT_SCREEN_WIDTH");
+    if (   !psz
+        || RTStrToUInt32Full(psz, 0, &cch) != VINF_SUCCESS
+        || cch == 0)
+    {
+        int rc = RTStrmQueryTerminalWidth(pStrm, &cch);
+        if (rc == VERR_INVALID_FUNCTION)
+        {
+            /* It's not a console, but in case we're being piped to less/more/list
+               we look for a console handle on the other standard output handle
+               and standard input.  (Latter doesn't work on windows.)  */
+            rc = RTStrmQueryTerminalWidth(pStrm == g_pStdErr ? g_pStdOut : g_pStdErr, &cch);
+            if (rc == VERR_INVALID_FUNCTION || rc == VERR_INVALID_HANDLE)
+                rc = RTStrmQueryTerminalWidth(g_pStdIn, &cch);
+            if (RT_FAILURE(rc))
+                cch = 80;
+        }
+    }
+
+    s_acch[iWhich] = cch;
+    return cch;
+}
+
+
+/**
+ * Prints a string table string (paragraph), performing non-breaking-space
+ * replacement and wrapping.
+ *
+ * @returns IRPT status code.
+ * @param   pStrm           The output stream.
+ * @param   psz             The string table string to print.
+ * @param   cchMaxWidth     The maximum output width.
+ * @param   fFlags          String flags that may affect formatting.
+ * @param   pcLinesWritten  Pointer to variable to update with written lines.
+ */
+static int printString(PRTSTREAM pStrm, const char *psz, uint32_t cchMaxWidth, uint64_t fFlags, uint32_t *pcLinesWritten)
+{
+    uint32_t    cLinesWritten;
+    size_t      cch     = strlen(psz);
+    const char *pszNbsp = strchr(psz, RTMSGREFENTRY_NBSP);
+    int         rc;
+
+    /*
+     * No-wrap case is simpler, so handle that separately.
+     */
+    if (cch <= cchMaxWidth)
+    {
+        if (!pszNbsp)
+            rc = RTStrmWrite(pStrm, psz, cch);
+        else
+        {
+            do
+            {
+                rc = RTStrmWrite(pStrm, psz, pszNbsp - psz);
+                if (RT_SUCCESS(rc))
+                    rc = RTStrmPutCh(pStrm, ' ');
+                psz = pszNbsp + 1;
+                pszNbsp = strchr(psz, RTMSGREFENTRY_NBSP);
+            } while (pszNbsp && RT_SUCCESS(rc));
+            if (RT_SUCCESS(rc))
+                rc = RTStrmWrite(pStrm, psz, strlen(psz));
+        }
+        if (RT_SUCCESS(rc))
+            rc = RTStrmPutCh(pStrm, '\n');
+        cLinesWritten = 1;
+    }
+    /*
+     * We need to wrap stuff, too bad.
+     */
+    else
+    {
+        /* Figure the paragraph indent level first. */
+        uint32_t cchIndent = 0;
+        while (*psz == ' ')
+            cchIndent++, psz++;
+        Assert(cchIndent + 4 + 1 <= RT_ELEMENTS(g_szSpaces));
+
+        if (cchIndent + 8 >= cchMaxWidth)
+            cchMaxWidth += cchIndent + 8;
+
+        /* Work our way thru the string, line by line. */
+        uint32_t cchHangingIndent = 0;
+        cLinesWritten = 0;
+        do
+        {
+            rc = RTStrmWrite(pStrm, g_szSpaces, cchIndent + cchHangingIndent);
+            if (RT_FAILURE(rc))
+                break;
+
+            size_t  offLine       = cchIndent + cchHangingIndent;
+            bool    fPendingSpace = false;
+            do
+            {
+                const char *pszSpace = strchr(psz, ' ');
+                size_t      cchWord  = pszSpace ? pszSpace - psz : strlen(psz);
+                if (   offLine + cchWord + fPendingSpace > cchMaxWidth
+                    && offLine != cchIndent
+                    && fPendingSpace /* don't stop before first word */)
+                    break;
+
+                pszNbsp = (const char *)memchr(psz, RTMSGREFENTRY_NBSP, cchWord);
+                while (pszNbsp)
+                {
+                    size_t cchSubWord = pszNbsp - psz;
+                    if (fPendingSpace)
+                    {
+                        rc = RTStrmPutCh(pStrm, ' ');
+                        if (RT_FAILURE(rc))
+                            break;
+                    }
+                    rc = RTStrmWrite(pStrm, psz, cchSubWord);
+                    if (RT_FAILURE(rc))
+                        break;
+                    offLine += cchSubWord + fPendingSpace;
+                    psz     += cchSubWord + 1;
+                    cchWord -= cchSubWord + 1;
+                    pszNbsp = (const char *)memchr(psz, RTMSGREFENTRY_NBSP, cchWord);
+                    fPendingSpace = true;
+                }
+                if (RT_FAILURE(rc))
+                    break;
+
+                if (fPendingSpace)
+                {
+                    rc = RTStrmPutCh(pStrm, ' ');
+                    if (RT_FAILURE(rc))
+                        break;
+                }
+                rc = RTStrmWrite(pStrm, psz, cchWord);
+                if (RT_FAILURE(rc))
+                    break;
+
+                offLine += cchWord + fPendingSpace;
+                psz      = pszSpace ? pszSpace + 1 : strchr(psz, '\0');
+                fPendingSpace = true;
+            } while (offLine < cchMaxWidth && *psz != '\0' && RT_SUCCESS(rc));
+
+            if (RT_SUCCESS(rc))
+                rc = RTStrmPutCh(pStrm, '\n');
+            if (RT_FAILURE(rc))
+                break;
+            cLinesWritten++;
+
+            /* Set up hanging indent if relevant. */
+            if (fFlags & RTMSGREFENTRYSTR_FLAGS_SYNOPSIS)
+                cchHangingIndent = 4;
+        } while (*psz != '\0');
+    }
+    *pcLinesWritten += cLinesWritten;
+    return rc;
+}
+
+
+/**
+ * Checks if the given string is empty (only spaces).
+ * @returns true if empty, false if not.
+ * @param   psz                 The string to examine.
+ */
+DECLINLINE(bool) isEmptyString(const char *psz)
+{
+    char ch;
+    while ((ch = *psz) == ' ')
+        psz++;
+    return ch == '\0';
+}
+
+
+/**
+ * Prints a string table.
+ *
+ * @returns Current number of pending blank lines.
+ * @param   pStrm               The output stream.
+ * @param   pStrTab             The string table.
+ * @param   fScope              The selection scope.
+ * @param   cPendingBlankLines  Pending blank lines from previous string table.
+ * @param   pcLinesWritten      Pointer to variable that should be incremented
+ *                              by the number of lines written.  Optional.
+ */
+RTDECL(int) RTMsgRefEntryPrintStringTable(PRTSTREAM pStrm, PCRTMSGREFENTRYSTRTAB pStrTab, uint64_t fScope,
+                                          uint32_t *pcPendingBlankLines, uint32_t *pcLinesWritten)
+{
+    uint32_t cPendingBlankLines = pcPendingBlankLines ? *pcPendingBlankLines : 0;
+    uint32_t cLinesWritten      = 0;
+    uint32_t cchWidth           = getScreenWidth(pStrm);
+    uint64_t fPrevScope         = fScope;
+    int      rc                 = VINF_SUCCESS;
+    for (uint32_t i = 0; i < pStrTab->cStrings; i++)
+    {
+        uint64_t fCurScope = pStrTab->paStrings[i].fScope;
+        if ((fCurScope & RTMSGREFENTRYSTR_SCOPE_MASK) == RTMSGREFENTRYSTR_SCOPE_SAME)
+        {
+            fCurScope &= ~RTMSGREFENTRYSTR_SCOPE_MASK;
+            fCurScope |= (fPrevScope & RTMSGREFENTRYSTR_SCOPE_MASK);
+        }
+        if (fCurScope & RTMSGREFENTRYSTR_SCOPE_MASK & fScope)
+        {
+            const char *psz = pStrTab->paStrings[i].psz;
+            if (psz && !isEmptyString(psz))
+            {
+                while (cPendingBlankLines > 0 && RT_SUCCESS(rc))
+                {
+                    cPendingBlankLines--;
+                    rc = RTStrmPutCh(pStrm, '\n');
+                    cLinesWritten++;
+                }
+                if (RT_SUCCESS(rc))
+                    rc = printString(pStrm, psz, cchWidth, fCurScope & RTMSGREFENTRYSTR_FLAGS_MASK, &cLinesWritten);
+                if (RT_FAILURE(rc))
+                    break;
+            }
+            else
+                cPendingBlankLines++;
+        }
+        fPrevScope = fCurScope;
+    }
+
+    if (pcLinesWritten)
+        *pcLinesWritten += cLinesWritten;
+    if (pcPendingBlankLines)
+        *pcPendingBlankLines = cPendingBlankLines;
+    return rc;
+}
+
+
+RTDECL(int) RTMsgRefEntrySynopsisEx(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry, uint64_t fScope, uint32_t fFlags)
+{
+    AssertReturn(!(fFlags & ~RTMSGREFENTRY_SYNOPSIS_F_USAGE), VERR_INVALID_FLAGS);
+
+    if (!pStrm)
+        pStrm = g_pStdOut;
+    int rc = VINF_SUCCESS;
+    if (fFlags & RTMSGREFENTRY_SYNOPSIS_F_USAGE)
+        RTStrmPutStr(pStrm, "Usage: ");
+    if (RT_SUCCESS(rc))
+        rc = RTMsgRefEntryPrintStringTable(pStrm, &pEntry->Synopsis, fScope, NULL, NULL);
+    return rc;
+}
+
+
+RTDECL(int) RTMsgRefEntrySynopsis(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry)
+{
+    return RTMsgRefEntrySynopsisEx(pStrm, pEntry, UINT64_MAX, true /*fPrintUsage*/);
+}
+
+
+RTDECL(int) RTMsgRefEntryHelpEx(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry, uint64_t fScope, uint32_t fFlags)
+{
+    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
+    if (!pStrm)
+        pStrm = g_pStdOut;
+    return RTMsgRefEntryPrintStringTable(pStrm, &pEntry->Help, fScope, NULL, NULL);
+}
+
+
+RTDECL(int) RTMsgRefEntryHelp(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry)
+{
+    return RTMsgRefEntryHelpEx(pStrm, pEntry, UINT64_MAX, 0 /*fFlags*/);
+}
+
