// Handle #line int TPpContext::CPPline(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); if (token == '\n') { parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", ""); return token; } int lineRes = 0; bool lineErr = false; token = eval(token, MIN_PRECEDENCE, lineRes, lineErr, ppToken); if (! lineErr) { if (token == '\n') ++lineRes; parseContext.setCurrentLine(lineRes); if (token != '\n') { int fileRes = 0; bool fileErr = false; token = eval(token, MIN_PRECEDENCE, fileRes, fileErr, ppToken); if (! fileErr) parseContext.setCurrentString(fileRes); } } token = extraTokenCheck(lineAtom, ppToken, token); return token; }
// Handle #line int TPpContext::CPPline(TPpToken* ppToken) { // "#line must have, after macro substitution, one of the following forms: // "#line line // "#line line source-string-number" int token = scanToken(ppToken); const TSourceLoc directiveLoc = ppToken->loc; if (token == '\n') { parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); return token; } int lineRes = 0; // Line number after macro expansion. int lineToken = 0; bool hasFile = false; int fileRes = 0; // Source file number after macro expansion. const char* sourceName = nullptr; // Optional source file name. bool lineErr = false; bool fileErr = false; token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); if (! lineErr) { lineToken = lineRes; if (token == '\n') ++lineRes; if (parseContext.lineDirectiveShouldSetNextLine()) --lineRes; parseContext.setCurrentLine(lineRes); if (token != '\n') { if (token == PpAtomConstString) { parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); // We need to save a copy of the string instead of pointing // to the name field of the token since the name field // will likely be overwritten by the next token scan. sourceName = GetAtomString(LookUpAddString(ppToken->name)); parseContext.setCurrentSourceName(sourceName); hasFile = true; token = scanToken(ppToken); } else { token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); if (! fileErr) { parseContext.setCurrentString(fileRes); hasFile = true; } } } } if (!fileErr && !lineErr) { parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName); } token = extraTokenCheck(PpAtomLine, ppToken, token); return token; }
// Handle #if int TPpContext::CPPif(TPpToken* ppToken) { int token = scanToken(ppToken); elsetracker++; ifdepth++; if (ifdepth > maxIfNesting) { parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); return 0; } int res = 0; bool err = false; token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken); token = extraTokenCheck(PpAtomIf, ppToken, token); if (!res && !err) token = CPPelse(1, ppToken); return token; }
// Handle #if int TPpContext::CPPif(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); elsetracker++; if (! ifdepth++) ifloc = ppToken->loc; if (ifdepth > maxIfNesting) { parseContext.error(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); return 0; } int res = 0; bool err = false; token = eval(token, MIN_PRECEDENCE, res, err, ppToken); token = extraTokenCheck(ifAtom, ppToken, token); if (!res && !err) token = CPPelse(1, ppToken); return token; }
int TPpContext::readCPPline(TPpToken* ppToken) { int token = scanToken(ppToken); if (token == PpAtomIdentifier) { switch (ppToken->atom) { case PpAtomDefine: token = CPPdefine(ppToken); break; case PpAtomElse: if (elsetracker[elseSeen]) parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); elsetracker[elseSeen] = true; if (! ifdepth) parseContext.ppError(ppToken->loc, "mismatched statements", "#else", ""); token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken)); token = CPPelse(0, ppToken); break; case PpAtomElif: if (! ifdepth) parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", ""); if (elseSeen[elsetracker]) parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); // this token is really a dont care, but we still need to eat the tokens token = scanToken(ppToken); while (token != '\n' && token != EndOfInput) token = scanToken(ppToken); token = CPPelse(0, ppToken); break; case PpAtomEndif: elseSeen[elsetracker] = false; --elsetracker; if (! ifdepth) parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", ""); else --ifdepth; token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken)); break; case PpAtomIf: token = CPPif(ppToken); break; case PpAtomIfdef: token = CPPifdef(1, ppToken); break; case PpAtomIfndef: token = CPPifdef(0, ppToken); break; case PpAtomInclude: parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include"); token = CPPinclude(ppToken); break; case PpAtomLine: token = CPPline(ppToken); break; case PpAtomPragma: token = CPPpragma(ppToken); break; case PpAtomUndef: token = CPPundef(ppToken); break; case PpAtomError: token = CPPerror(ppToken); break; case PpAtomVersion: token = CPPversion(ppToken); break; case PpAtomExtension: token = CPPextension(ppToken); break; default: parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name); break; } } else if (token != '\n' && token != EndOfInput) parseContext.ppError(ppToken->loc, "invalid directive", "#", ""); while (token != '\n' && token != EndOfInput) token = scanToken(ppToken); return token; }
/* Skip forward to appropriate spot. This is used both ** to skip to a #endif after seeing an #else, AND to skip to a #else, ** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false. */ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) { int atom; int depth = 0; int token = scanToken(ppToken); while (token != EndOfInput) { if (token != '#') { while (token != '\n' && token != EndOfInput) token = scanToken(ppToken); if (token == EndOfInput) return token; token = scanToken(ppToken); continue; } if ((token = scanToken(ppToken)) != PpAtomIdentifier) continue; atom = ppToken->atom; if (atom == PpAtomIf || atom == PpAtomIfdef || atom == PpAtomIfndef) { depth++; ifdepth++; elsetracker++; } else if (atom == PpAtomEndif) { token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); elseSeen[elsetracker] = false; --elsetracker; if (depth == 0) { // found the #endif we are looking for if (ifdepth) --ifdepth; break; } --depth; --ifdepth; } else if (matchelse && depth == 0) { if (atom == PpAtomElse) { elseSeen[elsetracker] = true; token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); // found the #else we are looking for break; } else if (atom == PpAtomElif) { if (elseSeen[elsetracker]) parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); /* we decrement ifdepth here, because CPPif will increment * it and we really want to leave it alone */ if (ifdepth) { --ifdepth; elseSeen[elsetracker] = false; --elsetracker; } return CPPif(ppToken); } } else if (atom == PpAtomElse) { if (elseSeen[elsetracker]) parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); else elseSeen[elsetracker] = true; token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); } else if (atom == PpAtomElif) { if (elseSeen[elsetracker]) parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); } } return token; }
int TPpContext::readCPPline(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); bool isVersion = false; if (token == CPP_IDENTIFIER) { if (ppToken->atom == defineAtom) { token = CPPdefine(ppToken); } else if (ppToken->atom == elseAtom) { if (! elsetracker[elseSeen]) { elsetracker[elseSeen] = true; if (! ifdepth) parseContext.error(ppToken->loc, "mismatched statements", "#else", ""); token = extraTokenCheck(elseAtom, ppToken, currentInput->scan(this, currentInput, ppToken)); token = CPPelse(0, ppToken); } else { parseContext.error(ppToken->loc, "#else after a #else", "#else", ""); ifdepth = 0; return 0; } } else if (ppToken->atom == elifAtom) { if (! ifdepth) parseContext.error(ppToken->loc, "mismatched statements", "#elif", ""); // this token is really a dont care, but we still need to eat the tokens token = currentInput->scan(this, currentInput, ppToken); while (token != '\n') token = currentInput->scan(this, currentInput, ppToken); token = CPPelse(0, ppToken); } else if (ppToken->atom == endifAtom) { elseSeen[elsetracker] = false; --elsetracker; if (! ifdepth) parseContext.error(ppToken->loc, "mismatched statements", "#endif", ""); else --ifdepth; token = extraTokenCheck(endifAtom, ppToken, currentInput->scan(this, currentInput, ppToken)); } else if (ppToken->atom == ifAtom) { token = CPPif (ppToken); } else if (ppToken->atom == ifdefAtom) { token = CPPifdef(1, ppToken); } else if (ppToken->atom == ifndefAtom) { token = CPPifdef(0, ppToken); } else if (ppToken->atom == lineAtom) { token = CPPline(ppToken); } else if (ppToken->atom == pragmaAtom) { token = CPPpragma(ppToken); } else if (ppToken->atom == undefAtom) { token = CPPundef(ppToken); } else if (ppToken->atom == errorAtom) { token = CPPerror(ppToken); } else if (ppToken->atom == versionAtom) { token = CPPversion(ppToken); isVersion = true; } else if (ppToken->atom == extensionAtom) { token = CPPextension(ppToken); } else { parseContext.error(ppToken->loc, "invalid directive:", "#", GetAtomString(ppToken->atom)); } } else if (token != '\n' && token > 0) parseContext.error(ppToken->loc, "invalid directive", "#", ""); while (token != '\n' && token != 0 && token != EOF) token = currentInput->scan(this, currentInput, ppToken); return token; }
/* Skip forward to appropriate spot. This is used both ** to skip to a #endif after seeing an #else, AND to skip to a #else, ** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false. */ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) { int atom; int depth = 0; int token = currentInput->scan(this, currentInput, ppToken); while (token != EOF) { if (token != '#') { while (token != '\n' && token != EOF) token = currentInput->scan(this, currentInput, ppToken); if (token == EOF) return EOF; token = currentInput->scan(this, currentInput, ppToken); continue; } if ((token = currentInput->scan(this, currentInput, ppToken)) != CPP_IDENTIFIER) continue; atom = ppToken->atom; if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom) { depth++; ifdepth++; elsetracker++; } else if (atom == endifAtom) { token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken)); elseSeen[elsetracker] = false; --elsetracker; if (depth == 0) { // found the #endif we are looking for if (ifdepth) --ifdepth; break; } --depth; --ifdepth; } else if (matchelse && depth == 0) { if (atom == elseAtom ) { token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken)); // found the #else we are looking for break; } else if (atom == elifAtom) { /* we decrement ifdepth here, because CPPif will increment * it and we really want to leave it alone */ if (ifdepth) { --ifdepth; elseSeen[elsetracker] = false; --elsetracker; } return CPPif(ppToken); } } else if (atom == elseAtom) { if (elseSeen[elsetracker]) parseContext.error(ppToken->loc, "#else after #else", "#else", ""); else elseSeen[elsetracker] = true; token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken)); } else if (atom == elifAtom) { if (elseSeen[elsetracker]) parseContext.error(ppToken->loc, "#elif after #else", "#else", ""); } } return token; }