VirtualBox

Ignore:
Timestamp:
Sep 25, 2017 8:04:07 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
118114
Message:

iprt,vboxmanage,manual: Try write the iso maker docs as a docbook refentry document. Tried to generalize the vboxmanage refentry output handling, moving it to RTMsg*. Made VBoxManage and IPRT generate their C/H sources in their own Makefiles. Hacked the C/H source generation till it can deal with the rather different RTIsoMaker command structure (no sub or sub-sub command stuff).

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk

    r65263 r68860  
    1818SUB_DEPTH = ../../../..
    1919include $(KBUILD_PATH)/subheader.kmk
     20
     21include $(PATH_ROOT)/doc/manual/Config.kmk
     22
    2023
    2124VBOX_COMMON_VBOXMANAGE_DEFS = \
     
    6164 VBoxManage_DEFS      += $(VBOX_COMMON_VBOXMANAGE_DEFS)
    6265 VBoxManage_DEFS.win   = _WIN32_WINNT=0x0500
    63  VBoxManage_INCS       = $(PATH_TARGET)/manual
    64  VBoxManage_INTERMEDIATES = $(PATH_TARGET)/manual/VBoxManageBuiltInHelp.h
     66 VBoxManage_INCS = \
     67        $(VBoxManage_0_OUTDIR)
     68 VBoxManage_INTERMEDIATES = \
     69        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h
    6570 VBoxManage_SOURCES    = \
    6671        VBoxManage.cpp \
     
    7681        $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
    7782        VBoxManageHelp.cpp \
    78         $(PATH_TARGET)/manual/VBoxManageBuiltInHelp.cpp \
     83        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \
    7984        VBoxManageHostonly.cpp \
    8085        VBoxManageInfo.cpp \
     
    109114endif
    110115
     116
     117#
     118# VBoxManage built-in help from XML refentry in doc/manual/en_US/.
     119#
     120$(call KB_FN_DO_PASS0_ON_TARGET,VBoxManage)
     121
     122VBoxManage_CLEAN += \
     123        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \
     124        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \
     125        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h \
     126        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \
     127       $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)))
     128
     129
     130
     131# Preprocess the xml files, applying remarks.
     132$(foreach file,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \
     133, $(evalcall2 def_vbox_refentry_preprocess_for_manpage,$(VBoxManage_0_OUTDIR),$(file),$(VBOX_PATH_MANUAL_SRC)/en_US/$(file)))
     134
     135
     136# Generate the .cpp file.
     137$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \
     138+| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp: \
     139                $(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) \
     140                $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
     141                $(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
     142        $(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
     143        $(QUIET)$(APPEND) -tn "$@" \
     144                '/* Autogenerated by $<, do not edit! */' \
     145                '' \
     146                '#include "VBoxManageBuiltInHelp.h"' \
     147                ''
     148        $(foreach refentry,$(filter %.xml,$^) \
     149        ,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") $< $(refentry))
     150        $(QUIET)$(APPEND) -n "$@" \
     151        '' \
     152                'PCRTMSGREFENTRY     g_apHelpEntries[] = ' \
     153                '{'
     154        $(foreach refentry,$(filter %.xml,$^) \
     155                ,$(NLTAB)$(QUIET)$(APPEND) -n "$@" \
     156                '    &g_$(subst -,_,$(tolower $(patsubst man_%,%,$(notdir $(basename $(refentry)))))), ')
     157        $(QUIET)$(APPEND) -n "$@" \
     158                '};' \
     159                'const uint32_t g_cHelpEntries = RT_ELEMENTS(g_apHelpEntries);' \
     160               ''
     161        $(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
     162# The above APPEND stuff trigger some kind of problem on some boxes when not split up...
     163# update: Fixed in SVN (strcpy -> memmove in new_job(), job.c - r2591). Just need to rebuild all platforms.
     164
     165
     166$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \
     167+| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h: \
     168                $(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) \
     169                $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \
     170                $(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@)
     171        $(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@))
     172        $(QUIET)$(APPEND) -tn "$@" \
     173                '/* Autogenerated by $<, do not edit! */' \
     174               '' \
     175               '#ifndef ___VBoxManageBuiltInHelp_h___' \
     176               '#define ___VBoxManageBuiltInHelp_h___' \
     177               '' \
     178               '#include <iprt/message.h>' \
     179               '' \
     180               'RT_C_DECLS_BEGIN' \
     181               '' \
     182               'typedef enum HELP_CMD_VBOXMANAGE' \
     183               '{' \
     184               '    HELP_CMD_VBOXMANAGE_INVALID = 0,'
     185        $(foreach refentry,$(filter %.xml,$^) \
     186        ,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
     187                --stringparam 'g_sMode' 'cmd' $< $(refentry))
     188        $(QUIET)$(APPEND) -n "$@" \
     189                '    HELP_CMD_VBOXMANAGE_END' \
     190                '} HELP_CMD_VBOXMANAGE;'
     191        $(foreach refentry,$(filter %.xml,$^) \
     192        ,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \
     193                --stringparam 'g_sMode' 'subcmd' $< $(refentry))
     194        $(QUIET)$(APPEND) -n "$@" \
     195                '' \
     196                'extern PCRTMSGREFENTRY g_apHelpEntries[];' \
     197                'extern const uint32_t  g_cHelpEntries;' \
     198                '' \
     199               'RT_C_DECLS_END' \
     200                '' \
     201                '#endif' \
     202               ''
     203        $(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)"
     204
     205
    111206include $(FILE_KBUILD_SUB_FOOTER)
     207
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp

    r68838 r68860  
    2828#include <iprt/getopt.h>
    2929#include <iprt/stream.h>
     30#include <iprt/message.h>
    3031
    3132#include "VBoxManage.h"
     
    4647enum HELP_CMD_VBOXMANAGE    g_enmCurCommand = HELP_CMD_VBOXMANAGE_INVALID;
    4748/** The scope maskt for the current subcommand. */
    48 uint64_t                    g_fCurSubcommandScope = REFENTRYSTR_SCOPE_GLOBAL;
     49uint64_t                    g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
    4950/** String of spaces that can be used for indentation.   */
    5051static const char           g_szSpaces[] = "                                                ";
     
    6162    Assert(g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID);
    6263    g_enmCurCommand       = enmCommand;
    63     g_fCurSubcommandScope = REFENTRYSTR_SCOPE_GLOBAL;
     64    g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
    6465}
    6566
     
    7879
    7980
    80 
    81 /**
    82  * Retruns the width for the given handle.
    83  *
    84  * @returns Screen width.
    85  * @param   pStrm           The stream, g_pStdErr or g_pStdOut.
    86  */
    87 static uint32_t getScreenWidth(PRTSTREAM pStrm)
    88 {
    89     static uint32_t s_acch[2] = { 0, 0 };
    90     uint32_t        iWhich    = pStrm == g_pStdErr ? 1 : 0;
    91     uint32_t        cch       = s_acch[iWhich];
    92     if (cch)
    93         return cch;
    94 
    95     const char *psz = RTEnvGet("VBOXMANAGE_SCREEN_WIDTH");
    96     if (   !psz
    97         || RTStrToUInt32Full(psz, 0, &cch) != VINF_SUCCESS
    98         || cch == 0)
    99     {
    100         int rc = RTStrmQueryTerminalWidth(pStrm, &cch);
    101         if (rc == VERR_INVALID_FUNCTION)
    102         {
    103             /* It's not a console, but in case we're being piped to less/more/list
    104                we look for a console handle on the other standard output handle
    105                and standard input.  (Latter doesn't work on windows.)  */
    106             rc = RTStrmQueryTerminalWidth(pStrm == g_pStdErr ? g_pStdOut : g_pStdErr, &cch);
    107             if (rc == VERR_INVALID_FUNCTION || rc == VERR_INVALID_HANDLE)
    108                 rc = RTStrmQueryTerminalWidth(g_pStdIn, &cch);
    109             if (RT_FAILURE(rc))
    110                 cch = 80;
    111         }
    112     }
    113 
    114     s_acch[iWhich] = cch;
    115     return cch;
    116 }
    117 
    118 
    119 /**
    120  * Prints a string table string (paragraph), performing non-breaking-space
    121  * replacement and wrapping.
    122  *
    123  * @returns Number of lines written.
    124  * @param   pStrm           The output stream.
    125  * @param   psz             The string table string to print.
    126  * @param   cchMaxWidth     The maximum output width.
    127  * @param   fFlags          String flags that may affect formatting.
    128  */
    129 static uint32_t printString(PRTSTREAM pStrm, const char *psz, uint32_t cchMaxWidth, uint64_t fFlags)
    130 {
    131     uint32_t    cLinesWritten;
    132     size_t      cch     = strlen(psz);
    133     const char *pszNbsp = strchr(psz, REFENTRY_NBSP);
    134 
    135     /*
    136      * No-wrap case is simpler, so handle that separately.
    137      */
    138     if (cch <= cchMaxWidth)
    139     {
    140         if (!pszNbsp)
    141             RTStrmWrite(pStrm, psz, cch);
    142         else
    143         {
    144             do
    145             {
    146                 RTStrmWrite(pStrm, psz, pszNbsp - psz);
    147                 RTStrmPutCh(pStrm, ' ');
    148                 psz = pszNbsp + 1;
    149                 pszNbsp = strchr(psz, REFENTRY_NBSP);
    150             } while (pszNbsp);
    151             RTStrmWrite(pStrm, psz, strlen(psz));
    152         }
    153         RTStrmPutCh(pStrm, '\n');
    154         cLinesWritten = 1;
    155     }
    156     /*
    157      * We need to wrap stuff, too bad.
    158      */
    159     else
    160     {
    161         /* Figure the paragraph indent level first. */
    162         uint32_t cchIndent = 0;
    163         while (*psz == ' ')
    164             cchIndent++, psz++;
    165         Assert(cchIndent + 4 + 1 <= RT_ELEMENTS(g_szSpaces));
    166 
    167         if (cchIndent + 8 >= cchMaxWidth)
    168             cchMaxWidth += cchIndent + 8;
    169 
    170         /* Work our way thru the string, line by line. */
    171         uint32_t cchHangingIndent = 0;
    172         cLinesWritten = 0;
    173         do
    174         {
    175             RTStrmWrite(pStrm, g_szSpaces, cchIndent + cchHangingIndent);
    176             size_t  offLine       = cchIndent + cchHangingIndent;
    177             bool    fPendingSpace = false;
    178             do
    179             {
    180                 const char *pszSpace = strchr(psz, ' ');
    181                 size_t      cchWord  = pszSpace ? pszSpace - psz : strlen(psz);
    182                 if (   offLine + cchWord + fPendingSpace > cchMaxWidth
    183                     && offLine != cchIndent
    184                     && fPendingSpace /* don't stop before first word */)
    185                     break;
    186 
    187                 pszNbsp = (const char *)memchr(psz, REFENTRY_NBSP, cchWord);
    188                 while (pszNbsp)
    189                 {
    190                     size_t cchSubWord = pszNbsp - psz;
    191                     if (fPendingSpace)
    192                         RTStrmPutCh(pStrm, ' ');
    193                     RTStrmWrite(pStrm, psz, cchSubWord);
    194                     offLine += cchSubWord + fPendingSpace;
    195                     psz     += cchSubWord + 1;
    196                     cchWord -= cchSubWord + 1;
    197                     pszNbsp = (const char *)memchr(psz, REFENTRY_NBSP, cchWord);
    198                     fPendingSpace = true;
    199                 }
    200 
    201                 if (fPendingSpace)
    202                     RTStrmPutCh(pStrm, ' ');
    203                 RTStrmWrite(pStrm, psz, cchWord);
    204                 offLine += cchWord + fPendingSpace;
    205                 psz      = pszSpace ? pszSpace + 1 : strchr(psz, '\0');
    206                 fPendingSpace = true;
    207             } while (offLine < cchMaxWidth && *psz != '\0');
    208             RTStrmPutCh(pStrm, '\n');
    209             cLinesWritten++;
    210 
    211             /* Set up hanging indent if relevant. */
    212             if (fFlags & REFENTRYSTR_FLAGS_SYNOPSIS)
    213                 cchHangingIndent = 4;
    214         } while (*psz != '\0');
    215     }
    216     return cLinesWritten;
    217 }
    218 
    219 
    220 /**
    221  * Checks if the given string is empty (only spaces).
    222  * @returns true if empty, false if not.
    223  * @param   psz                 The string to examine.
    224  */
    225 DECLINLINE(bool) isEmptyString(const char *psz)
    226 {
    227     char ch;
    228     while ((ch = *psz) == ' ')
    229         psz++;
    230     return ch == '\0';
    231 }
    232 
    233 
    234 /**
    235  * Prints a string table.
    236  *
    237  * @returns Current number of pending blank lines.
    238  * @param   pStrm               The output stream.
    239  * @param   pStrTab             The string table.
    240  * @param   fScope              The selection scope.
    241  * @param   cPendingBlankLines  Pending blank lines from previous string table.
    242  * @param   pcLinesWritten      Pointer to variable that should be incremented
    243  *                              by the number of lines written.  Optional.
    244  */
    245 static uint32_t printStringTable(PRTSTREAM pStrm, PCREFENTRYSTRTAB pStrTab, uint64_t fScope, uint32_t cPendingBlankLines,
    246                                  uint32_t *pcLinesWritten = NULL)
    247 {
    248     uint32_t cLinesWritten = 0;
    249     uint32_t cchWidth      = getScreenWidth(pStrm);
    250     uint64_t fPrevScope    = fScope;
    251     for (uint32_t i = 0; i < pStrTab->cStrings; i++)
    252     {
    253         uint64_t fCurScope = pStrTab->paStrings[i].fScope;
    254         if ((fCurScope & REFENTRYSTR_SCOPE_MASK) == REFENTRYSTR_SCOPE_SAME)
    255         {
    256             fCurScope &= ~REFENTRYSTR_SCOPE_MASK;
    257             fCurScope |= (fPrevScope & REFENTRYSTR_SCOPE_MASK);
    258         }
    259         if (fCurScope & REFENTRYSTR_SCOPE_MASK & fScope)
    260         {
    261             const char *psz = pStrTab->paStrings[i].psz;
    262             if (psz && !isEmptyString(psz))
    263             {
    264                 while (cPendingBlankLines > 0)
    265                 {
    266                     cPendingBlankLines--;
    267                     RTStrmPutCh(pStrm, '\n');
    268                     cLinesWritten++;
    269                 }
    270                 cLinesWritten += printString(pStrm, psz, cchWidth, fCurScope & REFENTRYSTR_FLAGS_MASK);
    271             }
    272             else
    273                 cPendingBlankLines++;
    274         }
    275         fPrevScope = fCurScope;
    276     }
    277 
    278     if (pcLinesWritten)
    279         *pcLinesWritten += cLinesWritten;
    280     return cPendingBlankLines;
    281 }
    28281
    28382
     
    29897    for (uint32_t i = 0; i < g_cHelpEntries; i++)
    29998    {
    300         PCREFENTRY pHelp = g_apHelpEntries[i];
     99        PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
    301100        if (pHelp->idInternal == (int64_t)enmCommand)
    302101        {
     
    304103            if (cFound == 1)
    305104            {
    306                 if (fSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL)
     105                if (fSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL)
    307106                    RTStrmPrintf(pStrm, "Usage - %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
    308107                else
    309108                    RTStrmPrintf(pStrm, "Usage:\n");
    310109            }
    311             cPendingBlankLines = printStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, cPendingBlankLines, &cLinesWritten);
     110            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, &cPendingBlankLines, &cLinesWritten);
    312111            if (!cPendingBlankLines)
    313112                cPendingBlankLines = 1;
     
    344143    for (uint32_t i = 0; i < g_cHelpEntries; i++)
    345144    {
    346         PCREFENTRY pHelp = g_apHelpEntries[i];
     145        PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
    347146        if (   pHelp->idInternal == (int64_t)enmCommand
    348147            || enmCommand == HELP_CMD_VBOXMANAGE_INVALID)
    349148        {
    350149            cFound++;
    351             cPendingBlankLines = printStringTable(pStrm, &pHelp->Help, fSubcommandScope, cPendingBlankLines);
     150            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Help, fSubcommandScope, &cPendingBlankLines, NULL /*pcLinesWritten*/);
    352151            if (cPendingBlankLines < 2)
    353152                cPendingBlankLines = 2;
     
    377176{
    378177    Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
    379     Assert(g_fCurSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL);
     178    Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
    380179
    381180    return errorSyntax("No subcommand specified");
     
    394193{
    395194    Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
    396     Assert(g_fCurSubcommandScope == REFENTRYSTR_SCOPE_GLOBAL);
     195    Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
    397196
    398197    /* check if help was requested. */
     
    421220{
    422221    Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
    423     Assert(g_fCurSubcommandScope != REFENTRYSTR_SCOPE_GLOBAL);
     222    Assert(g_fCurSubcommandScope != RTMSGREFENTRYSTR_SCOPE_GLOBAL);
    424223
    425224    /* check if help was requested. */
     
    14071206        for (uint32_t i = 0; i < g_cHelpEntries; i++)
    14081207        {
    1409             PCREFENTRY pHelp = g_apHelpEntries[i];
     1208            PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
    14101209            while (cPendingBlankLines-- > 0)
    14111210                RTStrmPutCh(pStrm, '\n');
    14121211            RTStrmPrintf(pStrm, " %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
    1413             cPendingBlankLines = printStringTable(pStrm, &pHelp->Synopsis, REFENTRYSTR_SCOPE_GLOBAL, 0);
     1212            cPendingBlankLines = 0;
     1213            RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, RTMSGREFENTRYSTR_SCOPE_GLOBAL,
     1214                                          &cPendingBlankLines, NULL /*pcLinesWritten*/);
    14141215            cPendingBlankLines = RT_MAX(cPendingBlankLines, 1);
    14151216        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette