ReturnCode State::execute(const string &code, string &err) { MSS_BEGIN(ReturnCode); CHECK_AND_LOCK(pimpl_); if (luaL_loadstring(s, code.c_str()) != 0) { err = lua_tostring(s, -1); MSS_L(CompileError); } err.clear(); if (lua_pcall(s, 0, 0, 0) != 0) { err = lua_tostring(s, -1); MSS_L(RuntimeError); } err.clear(); MSS_END(); }
ReturnCode read(Integer &v, const String &str, SInteger_tag) { MSS_BEGIN(ReturnCode); Range<String> range(str); Type type; MSS(range.read(type)); switch (type.primitive) { case Primitive::PosFix: v = type.nr; break; case Primitive::NegFix: v = type.nr-32; break; case Primitive::Int8: { char b; MSS(range.read(b)); v = b; } break; case Primitive::Int16: { char b; MSS(range.read(b)); v = b; v *= 256; unsigned char ub; MSS(range.read(ub)); v |= ub; } break; default: MSS_L(ReadError); break; } MSS_END(); }
ReturnCode process(const pp::Token &token) { MSS_BEGIN(ReturnCode); if (state_ == MacroInclude) { if (isLineFeed(token) || isCarriageReturn(token)) { receiver_().include_detected(include_.str(), IncludeType::Macro); include_.str(""); state_ = Idle; } else include_ << token.range.content(); } else if (token.isWhitespace()) { } else { switch (state_) { case Idle: if (isMacro(token) && token.range.content() == "include") state_ = IncludeDetected; break; case IncludeDetected: if (isString(token)) { const auto content = token.range.content(); MSS(content.front() == '"' && content.back() == '"', IllegalInclude); MSS(content.size() > 2, IllegalIncludeSize); receiver_().include_detected(content.substr(1, content.size()-2), IncludeType::Local); state_ = Idle; } else if (isSymbol(token)) { MSS(token.range.content() == "<"); include_.str(""); state_ = BeginBracketInclude; } else if (isIdentifier(token)) { include_.str(""); include_ << token.range.content(); state_ = MacroInclude; } else { std::ostringstream oss; oss << "I expected either a Symbol or a String, but I got a " << toString(token.type); receiver_().include_error(oss.str()); MSS_L(UnexpectedToken); } break; case BeginBracketInclude: switch (token.type) { case Token::Identifier: include_ << token.range.content(); break; case Token::Symbol: { const auto symbol = token.range.content(); assert(symbol.size() == 1); switch (symbol[0]) { case '.': case '/': include_ << symbol; break; case '>': receiver_().include_detected(include_.str(), IncludeType::System); include_.str(""); state_ = Idle; break; default: MSS_L(UnexpectedSymbol); break; } } break; default: MSS_L(UnexpectedToken); break; } break; } } MSS_END(); }
ReturnCode process(const gubg::file::File &file) { MSS_BEGIN(ReturnCode); Range range; MSS(gubg::file::read(range, file)); pp::Lexer<std::vector<pp::Token>> lexer; MSS(lexer.tokenize(range)); enum State {Idle, IncludeDetected, BeginBracketInclude, MacroInclude}; State state = Idle; std::ostringstream incl; auto &tokens = lexer.tokens(); for (auto it = tokens.begin(); it != tokens.end(); ++it) { auto &token = *it; typedef pp::Token Token; if (state == MacroInclude) { if (isLineFeed(token) || isCarriageReturn(token)) { receiver_().includes_detected(incl.str(), IncludeType::Macro); incl.str(""); state = Idle; } else incl << token.range.content(); continue; } if (token.isWhitespace()) continue; switch (state) { case Idle: if (isMacro(token) && token.range.content() == "include") state = IncludeDetected; break; case IncludeDetected: if (isString(token)) { const auto content = token.range.content(); MSS(content.front() == '"' && content.back() == '"', IllegalInclude); MSS(content.size() > 2, IllegalIncludeSize); receiver_().includes_detected(content.substr(1, content.size()-2), IncludeType::Local); state = Idle; } else if (isSymbol(token)) { MSS(token.range.content() == "<"); incl.str(""); state = BeginBracketInclude; } else if (isIdentifier(token)) { incl.str(""); incl << token.range.content(); state = MacroInclude; } else { std::ostringstream oss; oss << "I expected either a Symbol or a String, but I got a " << toString(token.type); receiver_().includes_error(oss.str()); MSS_L(UnexpectedToken); } break; case BeginBracketInclude: switch (token.type) { case Token::Identifier: incl << token.range.content(); break; case Token::Symbol: { const auto symbol = token.range.content(); assert(symbol.size() == 1); switch (symbol[0]) { case '.': case '/': case '-': case '+': incl << symbol; break; case '>': receiver_().includes_detected(incl.str(), IncludeType::System); incl.str(""); state = Idle; break; default: MSS_L(UnexpectedSymbol); break; } } break; default: MSS_L(UnexpectedToken); break; } break; } } if (state == MacroInclude) { receiver_().includes_detected(incl.str(), IncludeType::Macro); incl.str(""); state = Idle; } MSS_END(); }
ReturnCode decode(string &raw, const string &enc, QuoteStrategy qs) { MSS_BEGIN(ReturnCode); //We compute the size after decoding size_t rawSize = enc.size(); { gubg::Strange strange(enc); char ch; while (!strange.empty()) { if (strange.popCharIf('&')) { if (false) {} else if (strange.popString("quot;")) { MSS(rawSize >= 5); rawSize -= 5; } else if (strange.popString("lt;")) { MSS(rawSize >= 3); rawSize -= 3; } else if (strange.popString("gt;")) { MSS(rawSize >= 3); rawSize -= 3; } else if (strange.popString("amp;")) { MSS(rawSize >= 4); rawSize -= 4; } else if (strange.popString("apos;")) { MSS(rawSize >= 5); rawSize -= 5; } else if (strange.popString("#xa;") || strange.popString("#xA;") || strange.popString("#xd;") || strange.popString("#xD;")) { MSS(rawSize >= 4); rawSize -= 4; } else if (strange.popString("#x2018;") || strange.popString("#x2019;") || strange.popString("#x2026;") || strange.popString("#x201c;") || strange.popString("#x201d;")) { MSS(rawSize >= 7); rawSize -= 7; } else MSS_L(UnknownEscape); } else { const auto ret = strange.popChar(ch); assert(ret); switch (qs) { case DisallowQuote: MSS(ch != '"' && ch != '<' && ch != '>' && ch != '&', UnexpectedRawChar); break; case AllowQuote: MSS( ch != '<' && ch != '>' && ch != '&', UnexpectedRawChar); break; } } } } if (rawSize == enc.size()) //The encoded string _is_ the raw string raw = enc; else { raw.resize(rawSize); auto dst = raw.begin(); char ch; gubg::Strange strange(enc); while (!strange.empty()) { if (strange.popCharIf('&')) { if (false) {} else if (strange.popString("quot;") || strange.popString("#x201c;") || strange.popString("#x201d;")) *dst++ = '"'; else if (strange.popString("lt;")) *dst++ = '<'; else if (strange.popString("gt;")) *dst++ = '>'; else if (strange.popString("amp;")) *dst++ = '&'; else if (strange.popString("apos;")) *dst++ = '\''; else if (strange.popString("#xa;") || strange.popString("#xA;")) *dst++ = '\n'; else if (strange.popString("#xd;") || strange.popString("#xD;")) *dst++ = '\r'; else if (strange.popString("#x2018;")) *dst++ = '\''; else if (strange.popString("#x2019;")) *dst++ = '\''; else if (strange.popString("#x2026;")) //Elipsis *dst++ = '.'; else { //Should have failed above assert(false); } } else { strange.popChar(ch); *dst++ = ch; } } assert(dst == raw.end()); } MSS_END(); }