scm.cpp revision 6578276195b5b6a53ef2fc44f96a3348c516d3f5
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * IPRT Testcase / Tool - Source Code Massager.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Copyright (C) 2010 Sun Microsystems, Inc.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * available from http://www.virtualbox.org. This file is free software;
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * you can redistribute it and/or modify it under the terms of the GNU
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * General Public License (GPL) as published by the Free Software
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * The contents of this file may alternatively be used under the terms
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * of the Common Development and Distribution License Version 1.0
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * VirtualBox OSE distribution, in which case the provisions of the
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * CDDL are applicable instead of those of the GPL.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * You may elect to license modified versions of this file under the
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * terms and conditions of either the GPL or the CDDL or both.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * additional information or have any questions.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/*******************************************************************************
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync* Header Files *
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync*******************************************************************************/
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/*******************************************************************************
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync* Defined Constants And Macros *
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync*******************************************************************************/
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** The name of the settings files. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/*******************************************************************************
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync* Structures and Typedefs *
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync*******************************************************************************/
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** Pointer to const massager settings. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsynctypedef struct SCMSETTINGSBASE const *PCSCMSETTINGSBASE;
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** End of line marker type. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** Pointer to an end of line marker type. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Line record.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The offset of the line. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The line length, excluding the LF character.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * @todo This could be derived from the offset of the next line if that wasn't
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * so tedious. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The end of line marker type. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** Pointer to a line record. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * Source code massager stream.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsynctypedef struct SCMSTREAM
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Pointer to the file memory. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The current stream position. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The current stream size. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The size of the memory pb points to. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Line records. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** The current line. */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync /** The current stream size given in lines. */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync /** The sizeof the the memory backing paLines. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Set if write-only, clear if read-only. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Set if the memory pb points to is from RTFileReadAll. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Set if fully broken into lines. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Stream status code (IPRT). */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** Pointer to a SCM stream. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync/** Pointer to a const SCM stream. */
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * A rewriter.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * This works like a stream editor, reading @a pIn, modifying it and writing it
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * to @a pOut.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * @returns true if any changes were made, false if not.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * @param pIn The input stream.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * @param pOut The output stream.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync * @param pSettings The settings.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsynctypedef bool (*PFNSCMREWRITER)(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync * Configuration entry.
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsynctypedef struct SCMCFGENTRY
eb90548e8e40e597d65cdcc16ec958a3e09c1d73vboxsync /** Number of rewriters. */
const char *pszFilePattern;
} SCMCFGENTRY;
typedef struct SCMDIFFSTATE
const char *pszFilename;
bool fIgnoreEol;
bool fIgnoreTrailingWhite;
bool fIgnoreLeadingWhite;
bool fSpecialChars;
} SCMDIFFSTATE;
typedef struct SCMSETTINGSBASE
bool fConvertEol;
bool fConvertTabs;
bool fForceFinalEol;
bool fForceTrailingLine;
bool fStripTrailingBlanks;
bool fStripTrailingLines;
unsigned cchTab;
typedef enum SCMOPT
} SCMOPT;
typedef struct SCMPATRNOPTPAIR
char *pszPattern;
char *pszOptions;
typedef struct SCMSETTINGS
} SCMSETTINGS;
static bool rewrite_StripTrailingBlanks(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings);
static bool rewrite_AdjustTrailingLines(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings);
static bool g_fDryRun = true;
static bool g_fDiffSpecialChars = true;
static bool g_fDiffIgnoreEol = false;
static bool g_fDiffIgnoreLeadingWS = false;
static bool g_fDiffIgnoreTrailingWS = false;
static const char *g_pszFileFilterOut =
"*/src/VBox/Runtime/testcase/soundcard.h|"
static const char *g_pszDirFilterOut =
"*/src/VBox/Additions/x11/x11include/.|"
"*/src/VBox/HostServices/SharedOpenGL/.|"
"*/src/VBox/Devices/PC/Etherboot-src/*/.|"
"*/src/VBox/Devices/Storage/VBoxHDDFormats/StorageCraft/*/.|"
{ RT_ELEMENTS(g_aRewritersFor_C_and_CPP), &g_aRewritersFor_C_and_CPP[0], "*.c|*.h|*.cpp|*.hpp|*.C|*.CPP|*.cxx|*.cc" },
{ RT_ELEMENTS(g_aRewritersFor_BatchFiles), &g_aRewritersFor_BatchFiles[0], "*.bat|*.cmd|*.btm|*.vbs|*.ps1" },
void *pvFile;
return rc;
: _64K;
return VINF_SUCCESS;
void *pvNew;
if (!pvNew)
if (!pvNew)
return VINF_SUCCESS;
if (!pvNew)
return VINF_SUCCESS;
case SCMEOL_LF:
case SCMEOL_CRLF:
case SCMEOL_NONE:
return VINF_SUCCESS;
int rc;
#ifdef RT_STRICT
return rc;
rc = RTFileOpenV(&hFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE, pszFilenameFmt, va);
return rc;
return NULL;
return NULL;
return NULL;
cb--;
return pchRet;
return rc;
return VINF_SUCCESS;
static const char *ScmStreamGetLineByNo(PSCMSTREAM pStream, size_t iLine, size_t *pcchLine, PSCMEOL penmEol)
return NULL;
return NULL;
return NULL;
return pchRet;
if (!pchLine)
return cchLine == 0;
return enmEol;
return enmEol;
return rc;
return rc;
return rc;
iLine++;
return VINF_SUCCESS;
return rc;
iLine--;
if (!pchLF)
return rc;
if ( cchLine
cchLine--;
iLine++;
if (!pchLF)
return VINF_SUCCESS;
return VINF_SUCCESS;
while (cLines-- > 0)
if (!pchLine)
return rc;
return VINF_SUCCESS;
static void scmDiffPrintLines(PSCMDIFFSTATE pState, char chPrefix, PSCMSTREAM pStream, size_t iLine, size_t cLines)
while (cLines-- > 0)
while (pchTab)
switch (cchTab)
if (cchLeft)
iLine++;
if (c >= iLeft)
iLeft = c;
cLeft = 0;
if (c >= iRight)
iRight = c;
cRight = 0;
: cRight == 0
RTStrmPrintf(pState->pDiff, "%zu,%zu%c%zu,%zu\n", iLeft + 1, iLeft + cLeft, ch, iRight + 1, iRight + cRight);
if (cLeft)
if (cRight)
cchLeft--;
cchRight--;
const char *pchRight = ScmStreamGetLineByNo(pState->pRight, iRight + iLine, &cchRight, &enmEolRight);
* ones, including iStartLeft/Right.
if (!pchLine)
if (!pchLine)
size_t ScmDiffStreams(const char *pszFilename, PSCMSTREAM pLeft, PSCMSTREAM pRight, bool fIgnoreEol,
#ifdef RT_STRICT
const char *pchLeft;
const char *pchRight;
if (pchLeft)
else if (pchRight)
return VINF_SUCCESS;
if (pSettings)
switch (rc)
case SCMOPT_CONVERT_EOL:
return VINF_SUCCESS;
case SCMOPT_NO_CONVERT_EOL:
return VINF_SUCCESS;
case SCMOPT_CONVERT_TABS:
return VINF_SUCCESS;
case SCMOPT_NO_CONVERT_TABS:
return VINF_SUCCESS;
case SCMOPT_FORCE_FINAL_EOL:
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
case SCMOPT_TAB_SIZE:
return VERR_OUT_OF_RANGE;
return VINF_SUCCESS;
return VERR_GETOPT_UNKNOWN_OPTION;
int cArgs;
char **papszArgs;
rc = RTGetOptInit(&GetOptState, cArgs, papszArgs, &g_aScmOpts[0], RT_ELEMENTS(g_aScmOpts), 0, 0 /*fFlags*/);
return rc;
if (!pszLine)
return VERR_NO_MEMORY;
return rc;
return rc;
return VINF_SUCCESS;
if (!pSettings)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return rc;
if (pSettings)
if (!pchOptions)
return VERR_INVALID_PARAMETER;
pchOptions++;
cchPattern--;
cchOptions--;
return VINF_SUCCESS;
if (!pvNew)
return VERR_NO_MEMORY;
int rc;
return rc;
return rc;
const char *pchLine;
if (pchColon)
return rc;
static int scmSettingsCreateFromFile(PSCMSETTINGS *ppSettings, const char *pszFilename, PCSCMSETTINGSBASE pSettingsBase)
return VINF_SUCCESS;
return rc;
static int scmSettingsCreateForPath(PSCMSETTINGS *ppSettings, PCSCMSETTINGSBASE pBaseSettings, const char *pszPath)
return VERR_FILENAME_TOO_LONG;
return rc;
return rc;
if (pOld)
return VINF_SUCCESS;
return rc;
if (pNew)
if (pRet)
return pRet;
while (pCur)
if (cPairs)
return rc;
static bool rewrite_StripTrailingBlanks(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
bool fModified = false;
const char *pchLine;
int rc;
if ( cchLine == 0
cchLine--;
cchLine--;
fModified = true;
if (fModified)
return fModified;
bool fModified = false;
const char *pchLine;
int rc;
if (!pchTab)
if (!pchTab)
fModified = true;
if (fModified)
return fModified;
static bool rewrite_ForceEol(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings, SCMEOL enmDesiredEol)
bool fModified = false;
const char *pchLine;
fModified = true;
if (fModified)
return fModified;
static bool rewrite_AdjustTrailingLines(PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
cLinesNew--;
cLinesNew++;
if ( !fFixMissingEol
else if (fFixMissingEol)
static int scmProcessFileInner(const char *pszFilename, const char *pszBasename, size_t cchBasename,
if ( g_pszFileFilter
return VINF_SUCCESS;
if ( g_pszFileFilterOut
return VINF_SUCCESS;
if (RTStrSimplePatternMultiMatch(g_aConfigs[iCfg].pszFilePattern, RTSTR_MAX, pszBasename, cchBasename, NULL))
if (!pCfg)
return VINF_SUCCESS;
return rc;
bool fModified = false;
if (fRc)
fModified = true;
if (fModified)
if (!g_fDryRun)
return rc;
int rc = scmSettingsStackMakeFileBase(pSettingsStack, pszFilename, pszBasename, cchBasename, &Base);
return rc;
return RTDIRENTRYTYPE_UNKNOWN;
return RTDIRENTRYTYPE_DIRECTORY;
return RTDIRENTRYTYPE_FILE;
return RTDIRENTRYTYPE_UNKNOWN;
return rc;
return rc;
if (pszBasename)
return rc;
memcpy(&s_aOpts[RT_ELEMENTS(s_aOpts) - RT_ELEMENTS(g_aScmOpts)], &g_aScmOpts[0], sizeof(g_aScmOpts));
switch (rc)
g_fDryRun = true;
g_fDryRun = false;
g_iVerbosity = 0;
g_iVerbosity++;
case SCMOPT_DIFF_IGNORE_EOL:
g_fDiffIgnoreEol = true;
g_fDiffIgnoreEol = false;
case SCMOPT_DIFF_IGNORE_SPACE:
g_fDiffIgnoreLeadingWS = true;
g_fDiffIgnoreLeadingWS = false;
g_fDiffIgnoreTrailingWS = true;
g_fDiffIgnoreTrailingWS = false;
g_fDiffSpecialChars = true;
g_fDiffSpecialChars = false;
case VINF_GETOPT_NOT_OPTION:
if (!g_fDryRun)
if (!cProcessed)
cProcessed++;
return rc;