int MacroExpand(int atom, yystypepp * yylvalpp) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i,j, token, depth=0; const char *message; if (atom == __LINE__Atom) { yylvalpp->sc_int = GetLineNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->sc_int = GetStringNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING); yylvalpp->sc_int = atoi(yylvalpp->symbol_name); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (!sym || sym->details.mac.undef) return 0; if (sym->details.mac.busy) return 0; // no recursive expansions in = malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.scan = (void *)macro_scan; in->base.line = cpp->currentInput->line; in->base.name = cpp->currentInput->name; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->sc_ident = atom; return 0; } in->args = malloc(in->mac->argc * sizeof(TokenStream *)); for (i=0; i<in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i=0;j=0; do{ depth = 0; while(1) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } if((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if((in->mac->argc==1) &&j==0) break; i++; break; } i++; }while(i < in->mac->argc); if (i < in->mac->argc) { StoreStr("Too few args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } StoreStr("Too many args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } for (i=0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i=0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = cpp->currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); cpp->currentInput = &in->base; return 1; } // MacroExpand
/* MacroExpand ** Check an identifier (atom) to see if it is a macro that should be expanded. ** If it is, push an InputSrc that will produce the appropriate expansion ** and return 1. ** If it is, but undefined, it should expand to 0, push an InputSrc that will ** expand to 0 and return -1. ** Otherwise, return 0. */ int TPpContext::MacroExpand(int atom, TPpToken* yylvalpp, int expandUndef) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i, j, token; int depth = 0; if (atom == __LINE__Atom) { yylvalpp->ival = parseContext.currentLoc.line; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->ival = parseContext.currentLoc.string; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { yylvalpp->ival = parseContext.version; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } // no recursive expansions if (sym && sym->details.mac.busy) return 0; // not expanding of undefined symbols if ((! sym || sym->details.mac.undef) && ! expandUndef) return 0; in = (MacroInputSrc*)malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.line = currentInput->line; in->base.name = currentInput->name; if ((! sym || sym->details.mac.undef) && expandUndef) { // push input in->base.scan = zero_scan; in->base.prev = currentInput; currentInput = &in->base; return -1; } in->base.scan = macro_scan; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = currentInput->scan(this, currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->atom = atom; return 0; } in->args = (TokenStream**)malloc(in->mac->argc * sizeof(TokenStream *)); for (i = 0; i < in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i = 0; j = 0; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, yylvalpp); if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } if ((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if ((in->mac->argc==1) &&j==0) break; i++; break; } i++; } while (i < in->mac->argc); if (i < in->mac->argc) parseContext.error(yylvalpp->loc, "Too few args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = currentInput->scan(this, currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } parseContext.error(yylvalpp->loc, "Too many args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); } for (i = 0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i = 0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); currentInput = &in->base; return 1; } // MacroExpand
// // Check an identifier (atom) to see if it is a macro that should be expanded. // If it is, and defined, push a tInput that will produce the appropriate expansion // and return 1. // If it is, but undefined, and expandUndef is requested, push a tInput that will // expand to 0 and return -1. // Otherwise, return 0 to indicate no expansion, which is not necessarily an error. // int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay) { ppToken->space = false; switch (atom) { case PpAtomLineMacro: ppToken->ival = parseContext.getCurrentLoc().line; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; case PpAtomFileMacro: { if (parseContext.getCurrentLoc().name) parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); ppToken->ival = parseContext.getCurrentLoc().string; sprintf(ppToken->name, "%s", ppToken->loc.getStringNameOrNum().c_str()); UngetToken(PpAtomConstInt, ppToken); return 1; } case PpAtomVersionMacro: ppToken->ival = parseContext.version; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; default: break; } Symbol *sym = LookUpSymbol(atom); int token; int depth = 0; // no recursive expansions if (sym && sym->mac.busy) return 0; // not expanding undefined macros if ((! sym || sym->mac.undef) && ! expandUndef) return 0; // 0 is the value of an undefined macro if ((! sym || sym->mac.undef) && expandUndef) { pushInput(new tZeroInput(this)); return -1; } tMacroInput *in = new tMacroInput(this); TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->mac = &sym->mac; if (sym->mac.args) { token = scanToken(ppToken); if (newLineOkay) { while (token == '\n') token = scanToken(ppToken); } if (token != '(') { parseContext.ppError(loc, "expected '(' following", "macro expansion", GetAtomString(atom)); UngetToken(token, ppToken); ppToken->atom = atom; delete in; return 0; } in->args.resize(in->mac->argc); for (int i = 0; i < in->mac->argc; i++) in->args[i] = new TokenStream; int arg = 0; bool tokenRecorded = false; do { depth = 0; while (1) { token = scanToken(ppToken); if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); delete in; return 0; } if (token == '\n') { if (! newLineOkay) { parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", GetAtomString(atom)); delete in; return 0; } continue; } if (token == '#') { parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); delete in; return 0; } if (in->mac->argc == 0 && token != ')') break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[arg], token, ppToken); tokenRecorded = true; } if (token == ')') { if (in->mac->argc == 1 && tokenRecorded == 0) break; arg++; break; } arg++; } while (arg < in->mac->argc); if (arg < in->mac->argc) parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); else if (token != ')') { depth=0; while (token != EndOfInput && (depth > 0 || token != ')')) { if (token == ')') depth--; token = scanToken(ppToken); if (token == '(') depth++; } if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); delete in; return 0; } parseContext.ppError(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); } for (int i = 0; i < in->mac->argc; i++) in->args[i] = PrescanMacroArg(in->args[i], ppToken, newLineOkay); } pushInput(in); sym->mac.busy = 1; RewindTokenStream(sym->mac.body); return 1; }
/* ** Check an identifier (atom) to see if it is a macro that should be expanded. ** If it is, push an InputSrc that will produce the appropriate expansion ** and return 1. ** If it is, but undefined, it should expand to 0, push an InputSrc that will ** expand to 0 and return -1. ** Otherwise, return 0. */ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) { Symbol *sym = LookUpSymbol(atom); MacroInputSrc *in; int token; int depth = 0; if (atom == __LINE__Atom) { ppToken->ival = parseContext.getCurrentLoc().line; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } if (atom == __FILE__Atom) { ppToken->ival = parseContext.getCurrentLoc().string; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } if (atom == __VERSION__Atom) { ppToken->ival = parseContext.version; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } // no recursive expansions if (sym && sym->mac.busy) return 0; // not expanding of undefined symbols if ((! sym || sym->mac.undef) && ! expandUndef) return 0; in = new MacroInputSrc; if ((! sym || sym->mac.undef) && expandUndef) { // push input in->scan = zero_scan; in->prev = currentInput; currentInput = in; return -1; } TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->scan = macro_scan; in->mac = &sym->mac; if (sym->mac.args) { token = currentInput->scan(this, currentInput, ppToken); if (token != '(') { UngetToken(token, ppToken); ppToken->atom = atom; return 0; } in->args.resize(in->mac->argc); for (int i = 0; i < in->mac->argc; i++) in->args[i] = new TokenStream; int arg = 0; bool tokenRecorded = false; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, ppToken); if (token <= 0) { parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } if (token == '\n') { // TODO: Preprocessor functionality: Correctly handle new line and escaped new line, for expansions that are both in and not in another preprocessor directive //if (in a pp line) { // parseContext.error(loc, "missing ')':", "macro expansion", GetAtomString(atom)); // return 1; //} continue; } if (token == '#') { parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); return 1; } if (in->mac->argc == 0 && token != ')') break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[arg], token, ppToken); tokenRecorded = true; } if (token == ')') { if (in->mac->argc == 1 && tokenRecorded == 0) break; arg++; break; } arg++; } while (arg < in->mac->argc); if (arg < in->mac->argc) parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = currentInput->scan(this, currentInput, ppToken); if (token == '(') depth++; } if (token <= 0) { parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } parseContext.error(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); } for (int i = 0; i < in->mac->argc; i++) in->args[i] = PrescanMacroArg(in->args[i], ppToken); } /*retain the input source*/ in->prev = currentInput; sym->mac.busy = 1; RewindTokenStream(sym->mac.body); currentInput = in; return 1; }
// // Check a token to see if it is a macro that should be expanded. // If it is, and defined, push a tInput that will produce the appropriate expansion // and return 1. // If it is, but undefined, and expandUndef is requested, push a tInput that will // expand to 0 and return -1. // Otherwise, return 0 to indicate no expansion, which is not necessarily an error. // int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay) { ppToken->space = false; int macroAtom = atomStrings.getAtom(ppToken->name); switch (macroAtom) { case PpAtomLineMacro: ppToken->ival = parseContext.getCurrentLoc().line; snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; case PpAtomFileMacro: { if (parseContext.getCurrentLoc().name) parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); ppToken->ival = parseContext.getCurrentLoc().string; snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str()); UngetToken(PpAtomConstInt, ppToken); return 1; } case PpAtomVersionMacro: ppToken->ival = parseContext.version; snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; default: break; } MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom); int token; int depth = 0; // no recursive expansions if (macro != nullptr && macro->busy) return 0; // not expanding undefined macros if ((macro == nullptr || macro->undef) && ! expandUndef) return 0; // 0 is the value of an undefined macro if ((macro == nullptr || macro->undef) && expandUndef) { pushInput(new tZeroInput(this)); return -1; } tMacroInput *in = new tMacroInput(this); TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->mac = macro; if (macro->args.size() > 0 || macro->emptyArgs) { token = scanToken(ppToken); if (newLineOkay) { while (token == '\n') token = scanToken(ppToken); } if (token != '(') { parseContext.ppError(loc, "expected '(' following", "macro expansion", atomStrings.getString(macroAtom)); UngetToken(token, ppToken); delete in; return 0; } in->args.resize(in->mac->args.size()); for (size_t i = 0; i < in->mac->args.size(); i++) in->args[i] = new TokenStream; in->expandedArgs.resize(in->mac->args.size()); for (size_t i = 0; i < in->mac->args.size(); i++) in->expandedArgs[i] = nullptr; size_t arg = 0; bool tokenRecorded = false; do { depth = 0; while (1) { token = scanToken(ppToken); if (token == EndOfInput || token == tMarkerInput::marker) { parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); delete in; return 0; } if (token == '\n') { if (! newLineOkay) { parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom)); delete in; return 0; } continue; } if (token == '#') { parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom)); delete in; return 0; } if (in->mac->args.size() == 0 && token != ')') break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; in->args[arg]->putToken(token, ppToken); tokenRecorded = true; } if (token == ')') { if (in->mac->args.size() == 1 && tokenRecorded == 0) break; arg++; break; } arg++; } while (arg < in->mac->args.size()); if (arg < in->mac->args.size()) parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom)); else if (token != ')') { depth=0; while (token != EndOfInput && (depth > 0 || token != ')')) { if (token == ')') depth--; token = scanToken(ppToken); if (token == '(') depth++; } if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); delete in; return 0; } parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom)); } // We need both expanded and non-expanded forms of the argument, for whether or // not token pasting will be applied later when the argument is consumed next to ##. for (size_t i = 0; i < in->mac->args.size(); i++) in->expandedArgs[i] = PrescanMacroArg(*in->args[i], ppToken, newLineOkay); } pushInput(in); macro->busy = 1; macro->body.reset(); return 1; }
// // Check a token to see if it is a macro that should be expanded: // - If it is, and defined, push a tInput that will produce the appropriate // expansion and return MacroExpandStarted. // - If it is, but undefined, and expandUndef is requested, push a tInput // that will expand to 0 and return MacroExpandUndef. // - Otherwise, there is no expansion, and there are two cases: // * It might be okay there is no expansion, and no specific error was // detected. Returns MacroExpandNotStarted. // * The expansion was started, but could not be completed, due to an error // that cannot be recovered from. Returns MacroExpandError. // MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay) { ppToken->space = false; int macroAtom = atomStrings.getAtom(ppToken->name); switch (macroAtom) { case PpAtomLineMacro: ppToken->ival = parseContext.getCurrentLoc().line; snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return MacroExpandStarted; case PpAtomFileMacro: { if (parseContext.getCurrentLoc().name) parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); ppToken->ival = parseContext.getCurrentLoc().string; snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str()); UngetToken(PpAtomConstInt, ppToken); return MacroExpandStarted; } case PpAtomVersionMacro: ppToken->ival = parseContext.version; snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return MacroExpandStarted; default: break; } MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom); // no recursive expansions if (macro != nullptr && macro->busy) return MacroExpandNotStarted; // not expanding undefined macros if ((macro == nullptr || macro->undef) && ! expandUndef) return MacroExpandNotStarted; // 0 is the value of an undefined macro if ((macro == nullptr || macro->undef) && expandUndef) { pushInput(new tZeroInput(this)); return MacroExpandUndef; } tMacroInput *in = new tMacroInput(this); TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->mac = macro; if (macro->functionLike) { // We don't know yet if this will be a successful call of a // function-like macro; need to look for a '(', but without trashing // the passed in ppToken, until we know we are no longer speculative. TPpToken parenToken; int token = scanToken(&parenToken); if (newLineOkay) { while (token == '\n') token = scanToken(&parenToken); } if (token != '(') { // Function-like macro called with object-like syntax: okay, don't expand. // (We ate exactly one token that might not be white space; put it back. UngetToken(token, &parenToken); delete in; return MacroExpandNotStarted; } in->args.resize(in->mac->args.size()); for (size_t i = 0; i < in->mac->args.size(); i++) in->args[i] = new TokenStream; in->expandedArgs.resize(in->mac->args.size()); for (size_t i = 0; i < in->mac->args.size(); i++) in->expandedArgs[i] = nullptr; size_t arg = 0; bool tokenRecorded = false; do { TVector<char> nestStack; while (true) { token = scanToken(ppToken); if (token == EndOfInput || token == tMarkerInput::marker) { parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); delete in; return MacroExpandError; } if (token == '\n') { if (! newLineOkay) { parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom)); delete in; return MacroExpandError; } continue; } if (token == '#') { parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom)); delete in; return MacroExpandError; } if (in->mac->args.size() == 0 && token != ')') break; if (nestStack.size() == 0 && (token == ',' || token == ')')) break; if (token == '(') nestStack.push_back(')'); else if (token == '{' && parseContext.isReadingHLSL()) nestStack.push_back('}'); else if (nestStack.size() > 0 && token == nestStack.back()) nestStack.pop_back(); in->args[arg]->putToken(token, ppToken); tokenRecorded = true; } // end of single argument scan if (token == ')') { // closing paren of call if (in->mac->args.size() == 1 && !tokenRecorded) break; arg++; break; } arg++; } while (arg < in->mac->args.size()); // end of all arguments scan if (arg < in->mac->args.size()) parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom)); else if (token != ')') { // Error recover code; find end of call, if possible int depth = 0; while (token != EndOfInput && (depth > 0 || token != ')')) { if (token == ')' || token == '}') depth--; token = scanToken(ppToken); if (token == '(' || token == '{') depth++; } if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); delete in; return MacroExpandError; } parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom)); } // We need both expanded and non-expanded forms of the argument, for whether or // not token pasting will be applied later when the argument is consumed next to ##. for (size_t i = 0; i < in->mac->args.size(); i++) in->expandedArgs[i] = PrescanMacroArg(*in->args[i], ppToken, newLineOkay); } pushInput(in); macro->busy = 1; macro->body.reset(); return MacroExpandStarted; }