Beispiel #1
0
//
// Do all token-pasting related combining of two pasted tokens when getting a
// stream of tokens from a replacement list. Degenerates to no processing if a
// replacement list is not the source of the token stream.
//
int TPpContext::tokenPaste(int token, TPpToken& ppToken)
{
    // starting with ## is illegal, skip to next token
    if (token == PpAtomPaste) {
        _parseContext.ppError(ppToken.loc, "unexpected location", "##", "");
        return scanToken(&ppToken);
    }

    int resultToken = token; // "foo" pasted with "35" is an identifier, not a number

    // ## can be chained, process all in the chain at once
    while (peekPasting()) {
        TPpToken pastedPpToken;

        // next token has to be ##
        token = scanToken(&pastedPpToken);
        assert(token == PpAtomPaste);

        // This covers end of macro expansion
        if (endOfReplacementList()) {
            _parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
            break;
        }

        // get the token after the ##
        token = scanToken(&pastedPpToken);

        // This covers end of argument expansion
        if (token == tMarkerInput::marker) {
            _parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", "");
            break;
        }

        // get the token text
        switch (resultToken) {
        case PpAtomIdentifier:
            // already have the correct text in token.names
            break;
        case '=':
        case '!':
        case '-':
        case '~':
        case '+':
        case '*':
        case '/':
        case '%':
        case '<':
        case '>':
        case '|':
        case '^':
        case '&':
        case PpAtomRight:
        case PpAtomLeft:
        case PpAtomAnd:
        case PpAtomOr:
        case PpAtomXor:
            strcpy(ppToken.name, atomStrings.getString(resultToken));
            strcpy(pastedPpToken.name, atomStrings.getString(token));
            break;
        default:
            _parseContext.ppError(ppToken.loc, "not supported for these tokens", "##", "");
            return resultToken;
        }

        // combine the tokens
        if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength) {
            _parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", "");
            return resultToken;
        }
        strncat(ppToken.name, pastedPpToken.name, MaxTokenLength - strlen(ppToken.name));

        // correct the kind of token we are making, if needed (identifiers stay identifiers)
        if (resultToken != PpAtomIdentifier) {
            int newToken = atomStrings.getAtom(ppToken.name);
            if (newToken > 0)
                resultToken = newToken;
            else
                _parseContext.ppError(ppToken.loc, "combined token is invalid", "##", "");
        }
    }

    return resultToken;
}
Beispiel #2
0
//
// Do all token-pasting related combining of two pasted tokens when getting a
// stream of tokens from a replacement list. Degenerates to no processing if a
// replacement list is not the source of the token stream.
//
int TPpContext::tokenPaste(int token, TPpToken& ppToken)
{
    // starting with ## is illegal, skip to next token
    if (token == PpAtomPaste) {
        parseContext.ppError(ppToken.loc, "unexpected location", "##", "");
        return scanToken(&ppToken);
    }

    int resultToken = token; // "foo" pasted with "35" is an identifier, not a number

    // ## can be chained, process all in the chain at once
    while (peekPasting()) {
        TPpToken pastedPpToken;

        // next token has to be ##
        token = scanToken(&pastedPpToken);
        assert(token == PpAtomPaste);

        // This covers end of macro expansion
        if (endOfReplacementList()) {
            parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
            break;
        }

        // Get the token(s) after the ##.
        // Because of "space" semantics, and prior tokenization, what
        // appeared a single token, e.g. "3A", might have been tokenized
        // into two tokens "3" and "A", but the "A" will have 'space' set to
        // false.  Accumulate all of these to recreate the original lexical
        // appearing token.
        do {
            token = scanToken(&pastedPpToken);

            // This covers end of argument expansion
            if (token == tMarkerInput::marker) {
                parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", "");
                return resultToken;
            }

            // get the token text
            switch (resultToken) {
            case PpAtomIdentifier:
                // already have the correct text in token.names
                break;
            case '=':
            case '!':
            case '-':
            case '~':
            case '+':
            case '*':
            case '/':
            case '%':
            case '<':
            case '>':
            case '|':
            case '^':
            case '&':
            case PpAtomRight:
            case PpAtomLeft:
            case PpAtomAnd:
            case PpAtomOr:
            case PpAtomXor:
                snprintf(ppToken.name, sizeof(ppToken.name), "%s", atomStrings.getString(resultToken));
                snprintf(pastedPpToken.name, sizeof(pastedPpToken.name), "%s", atomStrings.getString(token));
                break;
            default:
                parseContext.ppError(ppToken.loc, "not supported for these tokens", "##", "");
                return resultToken;
            }

            // combine the tokens
            if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength) {
                parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", "");
                return resultToken;
            }
            snprintf(&ppToken.name[0] + strlen(ppToken.name), sizeof(ppToken.name) - strlen(ppToken.name),
                "%s", pastedPpToken.name);

            // correct the kind of token we are making, if needed (identifiers stay identifiers)
            if (resultToken != PpAtomIdentifier) {
                int newToken = atomStrings.getAtom(ppToken.name);
                if (newToken > 0)
                    resultToken = newToken;
                else
                    parseContext.ppError(ppToken.loc, "combined token is invalid", "##", "");
            }
        } while (peekContinuedPasting(resultToken));
    }

    return resultToken;
}