Changeset 68860 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Sep 25, 2017 8:04:07 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 118114
- Location:
- trunk/src/VBox/Frontends/VBoxManage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
r65263 r68860 18 18 SUB_DEPTH = ../../../.. 19 19 include $(KBUILD_PATH)/subheader.kmk 20 21 include $(PATH_ROOT)/doc/manual/Config.kmk 22 20 23 21 24 VBOX_COMMON_VBOXMANAGE_DEFS = \ … … 61 64 VBoxManage_DEFS += $(VBOX_COMMON_VBOXMANAGE_DEFS) 62 65 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 65 70 VBoxManage_SOURCES = \ 66 71 VBoxManage.cpp \ … … 76 81 $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \ 77 82 VBoxManageHelp.cpp \ 78 $( PATH_TARGET)/manual/VBoxManageBuiltInHelp.cpp \83 $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \ 79 84 VBoxManageHostonly.cpp \ 80 85 VBoxManageInfo.cpp \ … … 109 114 endif 110 115 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 122 VBoxManage_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 111 206 include $(FILE_KBUILD_SUB_FOOTER) 207 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
r68838 r68860 28 28 #include <iprt/getopt.h> 29 29 #include <iprt/stream.h> 30 #include <iprt/message.h> 30 31 31 32 #include "VBoxManage.h" … … 46 47 enum HELP_CMD_VBOXMANAGE g_enmCurCommand = HELP_CMD_VBOXMANAGE_INVALID; 47 48 /** The scope maskt for the current subcommand. */ 48 uint64_t g_fCurSubcommandScope = R EFENTRYSTR_SCOPE_GLOBAL;49 uint64_t g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL; 49 50 /** String of spaces that can be used for indentation. */ 50 51 static const char g_szSpaces[] = " "; … … 61 62 Assert(g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID); 62 63 g_enmCurCommand = enmCommand; 63 g_fCurSubcommandScope = R EFENTRYSTR_SCOPE_GLOBAL;64 g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL; 64 65 } 65 66 … … 78 79 79 80 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 ( !psz97 || RTStrToUInt32Full(psz, 0, &cch) != VINF_SUCCESS98 || 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/list104 we look for a console handle on the other standard output handle105 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-space121 * 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 else143 {144 do145 {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 else160 {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 do174 {175 RTStrmWrite(pStrm, g_szSpaces, cchIndent + cchHangingIndent);176 size_t offLine = cchIndent + cchHangingIndent;177 bool fPendingSpace = false;178 do179 {180 const char *pszSpace = strchr(psz, ' ');181 size_t cchWord = pszSpace ? pszSpace - psz : strlen(psz);182 if ( offLine + cchWord + fPendingSpace > cchMaxWidth183 && offLine != cchIndent184 && 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 incremented243 * 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 else273 cPendingBlankLines++;274 }275 fPrevScope = fCurScope;276 }277 278 if (pcLinesWritten)279 *pcLinesWritten += cLinesWritten;280 return cPendingBlankLines;281 }282 81 283 82 … … 298 97 for (uint32_t i = 0; i < g_cHelpEntries; i++) 299 98 { 300 PCR EFENTRY pHelp = g_apHelpEntries[i];99 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i]; 301 100 if (pHelp->idInternal == (int64_t)enmCommand) 302 101 { … … 304 103 if (cFound == 1) 305 104 { 306 if (fSubcommandScope == R EFENTRYSTR_SCOPE_GLOBAL)105 if (fSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL) 307 106 RTStrmPrintf(pStrm, "Usage - %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1); 308 107 else 309 108 RTStrmPrintf(pStrm, "Usage:\n"); 310 109 } 311 cPendingBlankLines = printStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope,cPendingBlankLines, &cLinesWritten);110 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, &cPendingBlankLines, &cLinesWritten); 312 111 if (!cPendingBlankLines) 313 112 cPendingBlankLines = 1; … … 344 143 for (uint32_t i = 0; i < g_cHelpEntries; i++) 345 144 { 346 PCR EFENTRY pHelp = g_apHelpEntries[i];145 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i]; 347 146 if ( pHelp->idInternal == (int64_t)enmCommand 348 147 || enmCommand == HELP_CMD_VBOXMANAGE_INVALID) 349 148 { 350 149 cFound++; 351 cPendingBlankLines = printStringTable(pStrm, &pHelp->Help, fSubcommandScope, cPendingBlankLines);150 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Help, fSubcommandScope, &cPendingBlankLines, NULL /*pcLinesWritten*/); 352 151 if (cPendingBlankLines < 2) 353 152 cPendingBlankLines = 2; … … 377 176 { 378 177 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); 379 Assert(g_fCurSubcommandScope == R EFENTRYSTR_SCOPE_GLOBAL);178 Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL); 380 179 381 180 return errorSyntax("No subcommand specified"); … … 394 193 { 395 194 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); 396 Assert(g_fCurSubcommandScope == R EFENTRYSTR_SCOPE_GLOBAL);195 Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL); 397 196 398 197 /* check if help was requested. */ … … 421 220 { 422 221 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); 423 Assert(g_fCurSubcommandScope != R EFENTRYSTR_SCOPE_GLOBAL);222 Assert(g_fCurSubcommandScope != RTMSGREFENTRYSTR_SCOPE_GLOBAL); 424 223 425 224 /* check if help was requested. */ … … 1407 1206 for (uint32_t i = 0; i < g_cHelpEntries; i++) 1408 1207 { 1409 PCR EFENTRY pHelp = g_apHelpEntries[i];1208 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i]; 1410 1209 while (cPendingBlankLines-- > 0) 1411 1210 RTStrmPutCh(pStrm, '\n'); 1412 1211 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*/); 1414 1215 cPendingBlankLines = RT_MAX(cPendingBlankLines, 1); 1415 1216 }
Note:
See TracChangeset
for help on using the changeset viewer.