Beispiel #1
0
/**
 * Strip trailing blanks (space & tab).
 *
 * @returns True if modified, false if not.
 * @param   pIn                 The input stream.
 * @param   pOut                The output stream.
 * @param   pSettings           The settings.
 */
bool rewrite_StripTrailingBlanks(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
{
    if (!pSettings->fStripTrailingBlanks)
        return false;

    bool        fModified = false;
    SCMEOL      enmEol;
    size_t      cchLine;
    const char *pchLine;
    while ((pchLine = ScmStreamGetLine(pIn, &cchLine, &enmEol)) != NULL)
    {
        int rc;
        if (    cchLine == 0
            ||  !RT_C_IS_BLANK(pchLine[cchLine - 1]) )
            rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
        else
        {
            cchLine--;
            while (cchLine > 0 && RT_C_IS_BLANK(pchLine[cchLine - 1]))
                cchLine--;
            rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
            fModified = true;
        }
        if (RT_FAILURE(rc))
            return false;
    }
    if (fModified)
        ScmVerbose(pState, 2, " * Stripped trailing blanks\n");
    return fModified;
}
Beispiel #2
0
/**
 * For converting the decomposition mappings field and similar.
 *
 * @returns Mapping array or NULL if none.
 * @param   psz                 The string to convert.  Can be empty.
 * @param   pcEntries           Where to store the number of entries.
 * @param   cMax                The max number of entries.
 */
static PRTUNICP ToMapping(char *psz, unsigned *pcEntries, unsigned cMax)
{
    PRTUNICP paCps  = NULL;
    unsigned cAlloc = 0;
    unsigned i      = 0;

    /* Convert the code points. */
    while (psz)
    {
        /* skip leading spaces */
        while (RT_C_IS_BLANK(*psz))
            psz++;

        /* the end? */
        if (!*psz)
            break;

        /* room left? */
        if (i >= cMax)
        {
            ParseError("Too many mappings.\n");
            break;
        }
        if (i >= cAlloc)
        {
            cAlloc += 4;
            paCps = (PRTUNICP)realloc(paCps, cAlloc * sizeof(paCps[0]));
            if (!paCps)
            {
                fprintf(stderr, "out of memory (%u)\n", (unsigned)(cAlloc * sizeof(paCps[0])));
                exit(1);
            }
        }

        /* Find the end. */
        char *pszThis = psz;
        while (RT_C_IS_XDIGIT(*psz))
            psz++;
        if (*psz && !RT_C_IS_BLANK(*psz))
            ParseError("Malformed mappings.\n");
        if (*psz)
            *psz++ = '\0';

        /* Convert to number and add it. */
        paCps[i++] = ToNum(pszThis);
    }

    *pcEntries = i;
    return paCps;
}
Beispiel #3
0
static void test3(void)
{
    RTTestISub("> 127");
    for (int ch = 128; ch < 2000000; ch++)
    {
        RTTESTI_CHECK(!RT_C_IS_CNTRL(ch));
        RTTESTI_CHECK(!RT_C_IS_SPACE(ch));
        RTTESTI_CHECK(!RT_C_IS_BLANK(ch));
        RTTESTI_CHECK(!RT_C_IS_PRINT(ch));
        RTTESTI_CHECK(!RT_C_IS_PUNCT(ch));
        RTTESTI_CHECK(!RT_C_IS_GRAPH(ch));
        RTTESTI_CHECK(!RT_C_IS_DIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_ALPHA(ch));
        RTTESTI_CHECK(!RT_C_IS_UPPER(ch));
        RTTESTI_CHECK(!RT_C_IS_LOWER(ch));
    }
}
Beispiel #4
0
static void test2(void)
{
    RTTestISub("< 0");
    for (int ch = -1; ch > -2000000; ch--)
    {
        RTTESTI_CHECK(!RT_C_IS_CNTRL(ch));
        RTTESTI_CHECK(!RT_C_IS_SPACE(ch));
        RTTESTI_CHECK(!RT_C_IS_BLANK(ch));
        RTTESTI_CHECK(!RT_C_IS_PRINT(ch));
        RTTESTI_CHECK(!RT_C_IS_PUNCT(ch));
        RTTESTI_CHECK(!RT_C_IS_GRAPH(ch));
        RTTESTI_CHECK(!RT_C_IS_DIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch));
        RTTESTI_CHECK(!RT_C_IS_ALPHA(ch));
        RTTESTI_CHECK(!RT_C_IS_UPPER(ch));
        RTTESTI_CHECK(!RT_C_IS_LOWER(ch));
    }
}
/**
 * Searches for the file in the path.
 *
 * The file is first tested without any path modification, then we walk the path
 * looking in each directory.
 *
 * @returns VBox status code.
 * @param   pszFilename     The file to search for.
 * @param   pszPath         The search path.
 * @param   pfnOpen         The open callback function.
 * @param   pvUser          User argument for the callback.
 */
static int dbgfR3AsSearchPath(const char *pszFilename, const char *pszPath, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser)
{
    char szFound[RTPATH_MAX];

    /* Check the filename length. */
    size_t const    cchFilename = strlen(pszFilename);
    if (cchFilename >= sizeof(szFound))
        return VERR_FILENAME_TOO_LONG;
    const char     *pszName = RTPathFilename(pszFilename);
    if (!pszName)
        return VERR_IS_A_DIRECTORY;
    size_t const    cchName = strlen(pszName);

    /*
     * Try default location first.
     */
    memcpy(szFound, pszFilename, cchFilename + 1);
    int rc = pfnOpen(szFound, pvUser);
    if (RT_SUCCESS(rc))
        return rc;

    /*
     * Walk the search path.
     */
    const char *psz = pszPath;
    while (*psz)
    {
        /* Skip leading blanks - no directories with leading spaces, thank you. */
        while (RT_C_IS_BLANK(*psz))
            psz++;

        /* Find the end of this element. */
        const char *pszNext;
        const char *pszEnd = strchr(psz, ';');
        if (!pszEnd)
            pszEnd = pszNext = strchr(psz, '\0');
        else
            pszNext = pszEnd + 1;
        if (pszEnd != psz)
        {
            size_t const cch = pszEnd - psz;
            if (cch + 1 + cchName < sizeof(szFound))
            {
                /** @todo RTPathCompose, RTPathComposeN(). This code isn't right
                 * for 'E:' on DOS systems. It may also create unwanted double slashes. */
                memcpy(szFound, psz, cch);
                szFound[cch] = '/';
                memcpy(szFound + cch + 1, pszName, cchName + 1);
                int rc2 = pfnOpen(szFound, pvUser);
                if (RT_SUCCESS(rc2))
                    return rc2;
                if (    rc2 != rc
                    &&  (   rc == VERR_FILE_NOT_FOUND
                         || rc == VERR_OPEN_FAILED))
                    rc = rc2;
            }
        }

        /* advance */
        psz = pszNext;
    }

    /*
     * Walk the path once again, this time do a depth search.
     */
    /** @todo do a depth search using the specified path. */

    /* failed */
    return rc;
}
Beispiel #6
0
/**
 * Attempts to convert an ISO date string to a time structure.
 *
 * We're a little forgiving with zero padding, unspecified parts, and leading
 * and trailing spaces.
 *
 * @retval  pTime on success,
 * @retval  NULL on failure.
 * @param   pTime       Where to store the time on success.
 * @param   pszString   The ISO date string to convert.
 */
RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString)
{
    /* Ignore leading spaces. */
    while (RT_C_IS_SPACE(*pszString))
        pszString++;

    /*
     * Init non date & time parts.
     */
    pTime->fFlags = RTTIME_FLAGS_TYPE_LOCAL;
    pTime->offUTC = 0;

    /*
     * The day part.
     */

    /* Year */
    int rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->i32Year);
    if (rc != VWRN_TRAILING_CHARS)
        return NULL;

    bool const fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
    if (fLeapYear)
        pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR;

    if (*pszString++ != '-')
        return NULL;

    /* Month of the year. */
    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Month);
    if (rc != VWRN_TRAILING_CHARS)
        return NULL;
    if (pTime->u8Month == 0 || pTime->u8Month > 12)
        return NULL;
    if (*pszString++ != '-')
        return NULL;

    /* Day of month.*/
    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8MonthDay);
    if (rc != VWRN_TRAILING_CHARS && rc != VINF_SUCCESS)
        return NULL;
    unsigned const cDaysInMonth = fLeapYear
                                ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
                                : g_acDaysInMonths[pTime->u8Month - 1];
    if (pTime->u8MonthDay == 0 || pTime->u8MonthDay > cDaysInMonth)
        return NULL;

    /* Calculate year day. */
    pTime->u16YearDay = pTime->u8MonthDay - 1
                      + (fLeapYear
                         ? g_aiDayOfYearLeap[pTime->u8Month - 1]
                         : g_aiDayOfYear[pTime->u8Month - 1]);

    /*
     * The time part.
     */
    if (*pszString++ != 'T')
        return NULL;

    /* Hour. */
    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Hour);
    if (rc != VWRN_TRAILING_CHARS)
        return NULL;
    if (pTime->u8Hour > 23)
        return NULL;
    if (*pszString++ != ':')
        return NULL;

    /* Minute. */
    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute);
    if (rc != VWRN_TRAILING_CHARS)
        return NULL;
    if (pTime->u8Minute > 59)
        return NULL;
    if (*pszString++ != ':')
        return NULL;

    /* Second. */
    rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute);
    if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
        return NULL;
    if (pTime->u8Second > 59)
        return NULL;

    /* Nanoseconds is optional and probably non-standard. */
    if (*pszString == '.')
    {
        rc = RTStrToUInt32Ex(pszString + 1, (char **)&pszString, 10, &pTime->u32Nanosecond);
        if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
            return NULL;
        if (pTime->u32Nanosecond >= 1000000000)
            return NULL;
    }
    else
        pTime->u32Nanosecond = 0;

    /*
     * Time zone.
     */
    if (*pszString == 'Z')
    {
        pszString++;
        pTime->fFlags &= ~RTTIME_FLAGS_TYPE_MASK;
        pTime->fFlags |= ~RTTIME_FLAGS_TYPE_UTC;
        pTime->offUTC = 0;
    }
    else if (   *pszString == '+'
             || *pszString == '-')
    {
        rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->offUTC);
        if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES)
            return NULL;
    }
    /* else: No time zone given, local with offUTC = 0. */

    /*
     * The rest of the string should be blanks.
     */
    char ch;
    while ((ch = *pszString++) != '\0')
        if (!RT_C_IS_BLANK(ch))
            return NULL;

    return pTime;
}
RTDECL(int) RTManifestReadStandardEx(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, char *pszErr, size_t cbErr)
{
    /*
     * Validate input.
     */
    AssertPtrNull(pszErr);
    if (pszErr && cbErr)
        *pszErr = '\0';
    RTMANIFESTINT *pThis = hManifest;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);

    /*
     * Process the stream line by line.
     */
    uint32_t iLine = 0;
    for (;;)
    {
        /*
         * Read a line from the input stream.
         */
        iLine++;
        char szLine[RTPATH_MAX + RTSHA512_DIGEST_LEN + 32];
        int rc = rtManifestReadLine(hVfsIos, szLine, sizeof(szLine));
        if (RT_FAILURE(rc))
        {
            if (rc == VERR_EOF)
                return VINF_SUCCESS;
            RTStrPrintf(pszErr, cbErr, "Error reading line #%u: %Rrc", iLine, rc);
            return rc;
        }
        if (rc != VINF_SUCCESS)
        {
            RTStrPrintf(pszErr, cbErr, "Line number %u is too long", iLine);
            return VERR_OUT_OF_RANGE;
        }

        /*
         * Strip it and skip if empty.
         */
        char *psz = RTStrStrip(szLine);
        if (!*psz)
            continue;

        /*
         * Read the attribute name.
         */
        const char * const pszAttr = psz;
        do
            psz++;
        while (!RT_C_IS_BLANK(*psz) && *psz);
        if (*psz)
            *psz++ = '\0';

        /*
         * The entry name is enclosed in parenthesis and followed by a '='.
         */
        psz = RTStrStripL(psz);
        if (*psz != '(')
        {
            RTStrPrintf(pszErr, cbErr, "Expected '(' after %zu on line %u", psz - szLine, iLine);
            return VERR_PARSE_ERROR;
        }
        const char * const pszName = ++psz;
        while (*psz)
        {
            if (*psz == ')')
            {
                char *psz2 = RTStrStripL(psz + 1);
                if (*psz2 == '=')
                {
                    *psz = '\0';
                    psz = psz2;
                    break;
                }
            }
            psz++;
        }

        if (*psz != '=')
        {
            RTStrPrintf(pszErr, cbErr, "Expected ')=' at %zu on line %u", psz - szLine, iLine);
            return VERR_PARSE_ERROR;
        }

        /*
         * The value.
         */
        psz = RTStrStrip(psz + 1);
        const char * const pszValue = psz;
        if (!*psz)
        {
            RTStrPrintf(pszErr, cbErr, "Expected value at %zu on line %u", psz - szLine, iLine);
            return VERR_PARSE_ERROR;
        }

        /*
         * Detect attribute type and sanity check the value.
         */
        uint32_t fType = RTMANIFEST_ATTR_UNKNOWN;
        static const struct
        {
            const char *pszAttr;
            uint32_t    fType;
            unsigned    cBits;
            unsigned    uBase;
        } s_aDecAttrs[] =
        {
            { "SIZE", RTMANIFEST_ATTR_SIZE, 64,  10}
        };
        for (unsigned i = 0; i < RT_ELEMENTS(s_aDecAttrs); i++)
            if (!strcmp(s_aDecAttrs[i].pszAttr, pszAttr))
            {
                fType = s_aDecAttrs[i].fType;
                rc = RTStrToUInt64Full(pszValue, s_aDecAttrs[i].uBase, NULL);
                if (rc != VINF_SUCCESS)
                {
                    RTStrPrintf(pszErr, cbErr, "Malformed value ('%s') at %zu on line %u: %Rrc", pszValue, psz - szLine, iLine, rc);
                    return VERR_PARSE_ERROR;
                }
                break;
            }

        if (fType == RTMANIFEST_ATTR_UNKNOWN)
        {
            static const struct
            {
                const char *pszAttr;
                uint32_t    fType;
                unsigned    cchHex;
            } s_aHexAttrs[] =
            {
                { "MD5",        RTMANIFEST_ATTR_MD5,        RTMD5_DIGEST_LEN    },
                { "SHA1",       RTMANIFEST_ATTR_SHA1,       RTSHA1_DIGEST_LEN   },
                { "SHA256",     RTMANIFEST_ATTR_SHA256,     RTSHA256_DIGEST_LEN },
                { "SHA512",     RTMANIFEST_ATTR_SHA512,     RTSHA512_DIGEST_LEN }
            };
            for (unsigned i = 0; i < RT_ELEMENTS(s_aHexAttrs); i++)
                if (!strcmp(s_aHexAttrs[i].pszAttr, pszAttr))
                {
                    fType = s_aHexAttrs[i].fType;
                    for (unsigned off = 0; off < s_aHexAttrs[i].cchHex; off++)
                        if (!RT_C_IS_XDIGIT(pszValue[off]))
                        {
                            RTStrPrintf(pszErr, cbErr, "Expected hex digit at %zu on line %u (value '%s', pos %u)",
                                        pszValue - szLine + off, iLine, pszValue, off);
                            return VERR_PARSE_ERROR;
                        }
                    break;
                }
        }

        /*
         * Finally, add it.
         */
        rc = RTManifestEntrySetAttr(hManifest, pszName, pszAttr, pszValue, fType);
        if (RT_FAILURE(rc))
        {
            RTStrPrintf(pszErr, cbErr, "RTManifestEntrySetAttr(,'%s','%s', '%s', %#x) failed on line %u: %Rrc",
                        pszName, pszAttr, pszValue, fType, iLine, rc);
            return rc;
        }
    }
}
Beispiel #8
0
/**
 * @callback_method_impl{dtrace_pops_t,dtps_provide}
 */
static void     vboxDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc)
{
    PSUPDRVVDTPROVIDERCORE  pProv = (PSUPDRVVDTPROVIDERCORE)pvProv;
    AssertPtrReturnVoid(pProv);
    LOG_DTRACE(("%s: %p / %p pDtProbeDesc=%p\n", __FUNCTION__, pProv, pProv->TracerData.DTrace.idProvider, pDtProbeDesc));

    if (pDtProbeDesc)
        return;  /* We don't generate probes, so never mind these requests. */

    if (pProv->TracerData.DTrace.fZombie)
        return;

    dtrace_provider_id_t const idProvider = pProv->TracerData.DTrace.idProvider;
    AssertPtrReturnVoid(idProvider);

    AssertPtrReturnVoid(pProv->pHdr);
    AssertReturnVoid(pProv->pHdr->offProbeLocs != 0);
    uint32_t const  cProbeLocs    = pProv->pHdr->cbProbeLocs / sizeof(VTGPROBELOC);

    /* Need a buffer for extracting the function names and mangling them in
       case of collision. */
    size_t const cbFnNmBuf = _4K + _1K;
    char *pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf);
    if (!pszFnNmBuf)
        return;

    /*
     * Itereate the probe location list and register all probes related to
     * this provider.
     */
    uint16_t const idxProv = (uint16_t)((PVTGDESCPROVIDER)((uintptr_t)pProv->pHdr + pProv->pHdr->offProviders) - pProv->pDesc);
    uint32_t idxProbeLoc;
    for (idxProbeLoc = 0; idxProbeLoc < cProbeLocs; idxProbeLoc++)
    {
        /* Skip probe location belonging to other providers or once that
           we've already reported. */
        PCVTGPROBELOC pProbeLocRO = &pProv->paProbeLocsRO[idxProbeLoc];
        PVTGDESCPROBE pProbeDesc  = pProbeLocRO->pProbe;
        if (pProbeDesc->idxProvider != idxProv)
            continue;

        uint32_t *pidProbe;
        if (!pProv->fUmod)
            pidProbe = (uint32_t *)&pProbeLocRO->idProbe;
        else
            pidProbe = &pProv->paR0ProbeLocs[idxProbeLoc].idProbe;
        if (*pidProbe != 0)
            continue;

        /* The function name may need to be stripped since we're using C++
           compilers for most of the code.  ASSUMES nobody are brave/stupid
           enough to use function pointer returns without typedef'ing
           properly them (e.g. signal). */
        const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName);
        const char *pszFunc    = pProbeLocRO->pszFunction;
        const char *psz        = strchr(pProbeLocRO->pszFunction, '(');
        size_t      cch;
        if (psz)
        {
            /* skip blanks preceeding the parameter parenthesis. */
            while (   (uintptr_t)psz > (uintptr_t)pProbeLocRO->pszFunction
                      && RT_C_IS_BLANK(psz[-1]))
                psz--;

            /* Find the start of the function name. */
            pszFunc = psz - 1;
            while ((uintptr_t)pszFunc > (uintptr_t)pProbeLocRO->pszFunction)
            {
                char ch = pszFunc[-1];
                if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':')
                    break;
                pszFunc--;
            }
            cch = psz - pszFunc;
        }
        else
            cch = strlen(pszFunc);
        RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch);

        /* Look up the probe, if we have one in the same function, mangle
           the function name a little to avoid having to deal with having
           multiple location entries with the same probe ID. (lazy bird) */
        Assert(!*pidProbe);
        if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
        {
            RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLocRO->uLine);
            if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
            {
                unsigned iOrd = 2;
                while (iOrd < 128)
                {
                    RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLocRO->uLine, iOrd);
                    if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE)
                        break;
                    iOrd++;
                }
                if (iOrd >= 128)
                {
                    LogRel(("VBoxDrv: More than 128 duplicate probe location instances %s at line %u in function %s [%s], probe %s\n",
                            pProbeLocRO->uLine, pProbeLocRO->pszFunction, pszFnNmBuf, pszPrbName));
                    continue;
                }
            }
        }

        /* Create the probe. */
        AssertCompile(sizeof(*pidProbe) == sizeof(dtrace_id_t));
        *pidProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName,
                                        1 /*aframes*/, (void *)(uintptr_t)idxProbeLoc);
        pProv->TracerData.DTrace.cProvidedProbes++;
    }

    RTMemFree(pszFnNmBuf);
    LOG_DTRACE(("%s: returns\n", __FUNCTION__));
}
/**
 * Looks for a PEM-like marker.
 *
 * @returns true if found, fasle if not.
 * @param   pbContent           Start of the content to search thru.
 * @param   cbContent           The size of the content to search.
 * @param   offStart            The offset into pbContent to start searching.
 * @param   pszLeadWord         The lead word (BEGIN/END).
 * @param   cchLeadWord         The length of the lead word.
 * @param   paMarkers           Pointer to an array of markers.
 * @param   cMarkers            Number of markers in the array.
 * @param   ppMatch             Where to return the pointer to the matching
 *                              marker. Optional.
 * @param   poffBegin           Where to return the start offset of the marker.
 *                              Optional.
 * @param   poffEnd             Where to return the end offset of the marker
 *                              (trailing whitespace and newlines will be
 *                              skipped).  Optional.
 */
static bool rtCrPemFindMarker(uint8_t const *pbContent, size_t cbContent, size_t offStart,
                              const char *pszLeadWord, size_t cchLeadWord, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
                              PCRTCRPEMMARKER *ppMatch, size_t *poffBegin, size_t *poffEnd)
{
    /* Remember the start of the content for the purpose of calculating offsets. */
    uint8_t const * const pbStart = pbContent;

    /* Skip adhead by offStart */
    if (offStart >= cbContent)
        return false;
    pbContent += offStart;
    cbContent -= offStart;

    /*
     * Search the content.
     */
    while (cbContent > 6)
    {
        /*
         * Look for dashes.
         */
        uint8_t const *pbStartSearch = pbContent;
        pbContent = (uint8_t const *)memchr(pbContent, '-', cbContent);
        if (!pbContent)
            break;

        cbContent -= pbContent - pbStartSearch;
        if (cbContent < 6)
            break;

        /*
         * There must be at least three to interest us.
         */
        if (   pbContent[1] == '-'
            && pbContent[2] == '-')
        {
            unsigned cDashes = 3;
            while (cDashes < cbContent && pbContent[cDashes] == '-')
                cDashes++;

            if (poffBegin)
                *poffBegin = pbContent - pbStart;
            cbContent -= cDashes;
            pbContent += cDashes;

            /*
             * Match lead word.
             */
            if (   cbContent > cchLeadWord
                && memcmp(pbContent, pszLeadWord, cchLeadWord) == 0
                && RT_C_IS_BLANK(pbContent[cchLeadWord]) )
            {
                pbContent += cchLeadWord;
                cbContent -= cchLeadWord;
                while (cbContent > 0 && RT_C_IS_BLANK(*pbContent))
                {
                    pbContent++;
                    cbContent--;
                }

                /*
                 * Match one of the specified markers.
                 */
                uint8_t const  *pbSavedContent = pbContent;
                size_t  const   cbSavedContent = cbContent;
                uint32_t        iMarker = 0;
                while (iMarker < cMarkers)
                {
                    pbContent = pbSavedContent;
                    cbContent = cbSavedContent;

                    uint32_t            cWords = paMarkers[iMarker].cWords;
                    PCRTCRPEMMARKERWORD pWord  = paMarkers[iMarker].paWords;
                    while (cWords > 0)
                    {
                        uint32_t const cchWord = pWord->cchWord;
                        if (cbContent <= cchWord)
                            break;
                        if (memcmp(pbContent, pWord->pszWord, cchWord))
                            break;
                        pbContent += cchWord;
                        cbContent -= cchWord;

                        if (!cbContent || !RT_C_IS_BLANK(*pbContent))
                            break;
                        do
                        {
                            pbContent++;
                            cbContent--;
                        } while (cbContent > 0 && RT_C_IS_BLANK(*pbContent));

                        cWords--;
                        if (cWords == 0)
                        {
                            /*
                             * If there are three or more dashes following now, we've got a hit.
                             */
                            if (   cbContent > 3
                                && pbContent[0] == '-'
                                && pbContent[1] == '-'
                                && pbContent[2] == '-')
                            {
                                cDashes = 3;
                                while (cDashes < cbContent && pbContent[cDashes] == '-')
                                    cDashes++;
                                cbContent -= cDashes;
                                pbContent += cDashes;

                                /*
                                 * Skip spaces and newline.
                                 */
                                while (cbContent > 0 && RT_C_IS_SPACE(*pbContent))
                                    pbContent++, cbContent--;
                                if (poffEnd)
                                    *poffEnd = pbContent - pbStart;
                                if (*ppMatch)
                                    *ppMatch = &paMarkers[iMarker];
                                return true;
                            }
                            break;
                        }
                    } /* for each word in marker. */
                } /* for each marker. */
            }
        }
        else
        {
            pbContent++;
            cbContent--;
        }
    }

    return false;
}
/**
 * Get the next token from the config stream and create a token structure.
 *
 * @returns VBox status code.
 * @param   pCfgTokenizer    The config tokenizer data.
 * @param   pCfgTokenUse     Allocated token structure to use or NULL to allocate
 *                           a new one. It will bee freed if an error is encountered.
 * @param   ppCfgToken       Where to store the pointer to the next token on success.
 */
static int autostartConfigTokenizerCreateToken(PCFGTOKENIZER pCfgTokenizer,
                                               PCFGTOKEN pCfgTokenUse, PCFGTOKEN *ppCfgToken)
{
    const char *pszToken = NULL;
    size_t cchToken = 1;
    size_t cchAdvance = 0;
    CFGTOKENTYPE enmType = CFGTOKENTYPE_INVALID;
    int rc = VINF_SUCCESS;

    for (;;)
    {
        pszToken = pCfgTokenizer->pszLineCurr;

        /* Skip all spaces. */
        while (RT_C_IS_BLANK(*pszToken))
        {
            pszToken++;
            cchAdvance++;
        }

        /* Check if we have to read a new line. */
        if (   *pszToken == '\0'
            || *pszToken == '#')
        {
            rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
            if (rc == VERR_EOF)
            {
                enmType = CFGTOKENTYPE_EOF;
                rc = VINF_SUCCESS;
                break;
            }
            else if (RT_FAILURE(rc))
                break;
            /* start from the beginning. */
            cchAdvance = 0;
        }
        else if (*pszToken == '=')
        {
            enmType = CFGTOKENTYPE_EQUAL;
            break;
        }
        else if (*pszToken == ',')
        {
            enmType = CFGTOKENTYPE_COMMA;
            break;
        }
        else if (*pszToken == '{')
        {
            enmType = CFGTOKENTYPE_CURLY_OPEN;
            break;
        }
        else if (*pszToken == '}')
        {
            enmType = CFGTOKENTYPE_CURLY_CLOSING;
            break;
        }
        else
        {
            const char *pszTmp = pszToken;
            cchToken = 0;
            enmType = CFGTOKENTYPE_ID;

            /* Get the complete token. */
            while (   RT_C_IS_ALNUM(*pszTmp)
                   || *pszTmp == '_'
                   || *pszTmp == '.')
            {
                pszTmp++;
                cchToken++;
            }
            break;
        }
    }

    Assert(RT_FAILURE(rc) || enmType != CFGTOKENTYPE_INVALID);

    if (RT_SUCCESS(rc))
    {
        /* Free the given token if it is an ID or the current one is an ID token. */
        if (   pCfgTokenUse
            && (   pCfgTokenUse->enmType == CFGTOKENTYPE_ID
                || enmType == CFGTOKENTYPE_ID))
        {
            autostartConfigTokenFree(pCfgTokenizer, pCfgTokenUse);
            pCfgTokenUse = NULL;
        }

        if (!pCfgTokenUse)
        {
            size_t cbToken = sizeof(CFGTOKEN);
            if (enmType == CFGTOKENTYPE_ID)
                cbToken += (cchToken + 1) * sizeof(char);

            pCfgTokenUse = (PCFGTOKEN)RTMemAllocZ(cbToken);
            if (!pCfgTokenUse)
                rc = VERR_NO_MEMORY;
        }

        if (RT_SUCCESS(rc))
        {
            /* Copy token data. */
            pCfgTokenUse->enmType  = enmType;
            pCfgTokenUse->cchStart = pCfgTokenizer->cchCurr;
            pCfgTokenUse->iLine    = pCfgTokenizer->iLine;
            if (enmType == CFGTOKENTYPE_ID)
            {
                pCfgTokenUse->u.Id.cchToken = cchToken;
                memcpy(pCfgTokenUse->u.Id.achToken, pszToken, cchToken);
            }
        }
        else if (pCfgTokenUse)
            autostartConfigTokenFree(pCfgTokenizer, pCfgTokenUse);

        if (RT_SUCCESS(rc))
        {
            /* Set new position in config stream. */
            pCfgTokenizer->pszLineCurr += cchToken + cchAdvance;
            pCfgTokenizer->cchCurr     += cchToken + cchAdvance;
            *ppCfgToken                 = pCfgTokenUse;
        }
    }

    return rc;
}
/**
 * Tries to open the file using the image search paths.
 *
 * This is currently a quick hack and the only way to specifying the path is by setting
 * VBOXDBG_IMAGE_PATH in the environment. It uses semicolon as separator everywhere.
 *
 * @returns VBox status code.
 * @param   pVM             The VM handle.
 * @param   pszFilename     The name of the file to locate and open.
 * @param   pszFound        Where to return the actual filename.
 * @param   cchFound        The buffer size.
 * @param   ppFile          Where to return the opened file.
 */
int dbgfR3ModuleLocateAndOpen(PVM pVM, const char *pszFilename, char *pszFound, size_t cchFound, FILE **ppFile)
{
    /* Check the filename length. */
    size_t const    cchFilename = strlen(pszFilename);
    if (cchFilename >= cchFound)
        return VERR_FILENAME_TOO_LONG;
    const char     *pszName = RTPathFilename(pszFilename);
    if (!pszName)
        return VERR_IS_A_DIRECTORY;
    size_t const    cchName = strlen(pszName);

    /*
     * Try default location first.
     */
    memcpy(pszFound, pszFilename, cchFilename + 1);
    FILE *pFile = *ppFile = fopen(pszFound, "rb");
    if (pFile)
        return VINF_SUCCESS;

    /*
     * Walk the search path.
     */
    char *pszFreeMe = RTEnvDupEx(RTENV_DEFAULT, "VBOXDBG_IMAGE_PATH");
    const char *psz = pszFreeMe ? pszFreeMe : ".";
    while (*psz)
    {
        /* Skip leading blanks - no directories with leading spaces, thank you. */
        while (RT_C_IS_BLANK(*psz))
            psz++;

        /* Fine the end of this element. */
        const char *pszNext;
        const char *pszEnd = strchr(psz, ';');
        if (!pszEnd)
            pszEnd = pszNext = strchr(psz, '\0');
        else
            pszNext = pszEnd + 1;
        if (pszEnd != psz)
        {
            size_t const cch = pszEnd - psz;
            if (cch + 1 + cchName < cchFound)
            {
                /** @todo RTPathCompose, RTPathComposeN(). This code isn't right
                 * for 'E:' on DOS systems. It may also create unwanted double slashes. */
                memcpy(pszFound, psz, cch);
                pszFound[cch] = '/';
                memcpy(pszFound + cch + 1, pszName, cchName + 1);
                *ppFile = pFile = fopen(pszFound, "rb");
                if (pFile)
                {
                    RTStrFree(pszFreeMe);
                    return VINF_SUCCESS;
                }
            }

            /** @todo do a depth search using the specified path. */
        }

        /* advance */
        psz = pszNext;
    }

    /* not found */
    RTStrFree(pszFreeMe);
    return VERR_OPEN_FAILED;
}