// // 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; }
// // 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; }