bool CmdLineParser::_ParseAffinity()

in CmdLineParser/CmdLineParser.cpp [403:545]


bool CmdLineParser::_ParseAffinity(const char *arg, TimeSpan *pTimeSpan)
{
    bool fOk = true;

    assert(nullptr != arg);
    assert('\0' != *arg);

    const char *c = arg + 1;

    // -a and -ag are functionally equivalent; group-aware affinity.
    // Note that group-aware affinity is default.

    // look for the -a simple case
    if (*c == '\0')
    {
        return true;
    }

    // look for the -ag simple case
    if (*c == 'g')
    {
        // peek ahead, done?
        if (*(c + 1) == '\0')
        {
            return true;
        }

        // leave the parser at the g; this is the start of a group number
    }

    // more complex affinity -ag0,0,1,2,g1,0,1,2,... OR -a0,1,2,..
    // n counts the -a prefix, the first parsed character is string index 2
    DWORD nGroup = 0, nNum = 0, n = 2;
    bool fGroup = false, fNum = false;
    while (*c != '\0')
    {
        if ((*c >= '0') && (*c <= '9'))
        {
            // accumulating a number
            fNum = true;
            nNum = 10 * nNum + (*c - '0');
        }
        else if (*c == 'g')
        {
            // bad: ggggg
            if (fGroup)
            {
                fOk = false;
            }

            // now parsing a group number
            fGroup = true;
        }
        else if (*c == ',')
        {
            // separator; if parsing group and have a number, now have the group
            if (fGroup && fNum)
            {
                if (nNum > MAXWORD)
                {
                    fprintf(stderr, "ERROR: group %u is out of range\n", nNum);
                    fOk = false;
                }
                else
                {
                    nGroup = nNum;
                    nNum = 0;
                    fGroup = false;
                }
            }
            // at a split but don't have a parsed number, error
            else if (!fNum)
            {
                fOk = false;
            }
            // have a parsed core number
            else
            {
                if (nNum > MAXBYTE)
                {
                    fprintf(stderr, "ERROR: core %u is out of range\n", nNum);
                    fOk = false;
                }
                else
                {
                    pTimeSpan->AddAffinityAssignment((WORD)nGroup, (BYTE)nNum);
                    nNum = 0;
                    fNum = false;
                }
            }
        }
        else
        {
            fOk = false;
        }

        // bail out to error pretty print on error
        if (!fOk)
        {
            break;
        }

        c++;
        n++;
    }

    // if parsing a group or don't have a final number, error
    if (fGroup || !fNum)
    {
        fOk = false;
    }

    if (fOk && nNum > MAXBYTE)
    {
        fprintf(stderr, "ERROR: core %u is out of range\n", nNum);
        fOk = false;
    }

    if (!fOk)
    {
        // mid-parse error, show the point at which it occured
        if (*c != '\0') {
            fprintf(stderr, "ERROR: syntax error parsing affinity at highlighted character\n-%s\n", arg);
            while (n-- > 0)
            {
                fprintf(stderr, " ");
            }
            fprintf(stderr, "^\n");
        }
        else
        {
            fprintf(stderr, "ERROR: incomplete affinity specification\n");
        }
    }

    if (fOk)
    {
        // fprintf(stderr, "FINAL parsed group %d core %d\n", nGroup, nNum);
        pTimeSpan->AddAffinityAssignment((WORD)nGroup, (BYTE)nNum);
    }

    return fOk;
}