uint64 ExpressionParser::_ParseProduct() { uint64 value = _ParseUnary(); while (true) { Token token = fTokenizer.NextToken(); switch (token.type) { case TOKEN_STAR: value = value * _ParseUnary(); break; case TOKEN_SLASH: { uint64 rhs = _ParseUnary(); if (rhs == 0) parse_exception("division by zero", token.position); value = value / rhs; break; } case TOKEN_MODULO: { uint64 rhs = _ParseUnary(); if (rhs == 0) parse_exception("modulo by zero", token.position); value = value % rhs; break; } default: fTokenizer.RewindToken(); return value; } } }
uint64 ExpressionParser::_ParseDereference(void** _address, uint32* _size) { int32 starPosition = fTokenizer.CurrentToken().position; // optional "{ ... }" specifying the size to read uint64 size = 4; if (fTokenizer.NextToken().type == TOKEN_OPENING_BRACE) { int32 position = fTokenizer.CurrentToken().position; size = _ParseExpression(); if (size != 1 && size != 2 && size != 4 && size != 8) { snprintf(sTempBuffer, sizeof(sTempBuffer), "invalid size (%" B_PRIu64 ") for unary * operator", size); parse_exception(sTempBuffer, position); } _EatToken(TOKEN_CLOSING_BRACE); } else fTokenizer.RewindToken(); const void* address = (const void*)(addr_t)_ParseUnary(); // read bytes from address into a tempory buffer uint64 buffer; if (debug_memcpy(B_CURRENT_TEAM, &buffer, address, size) != B_OK) { snprintf(sTempBuffer, sizeof(sTempBuffer), "failed to dereference address %p", address); parse_exception(sTempBuffer, starPosition); } // convert the value to uint64 uint64 value = 0; switch (size) { case 1: value = *(uint8*)&buffer; break; case 2: value = *(uint16*)&buffer; break; case 4: value = *(uint32*)&buffer; break; case 8: value = buffer; break; } if (_address != NULL) *_address = (void*)address; if (_size != NULL) *_size = size; return value; }
void ExpressionParser::_ParseCommand(debugger_command_pipe_segment& segment) { fTokenizer.SetCommandMode(false); const Token& token = _EatToken(TOKEN_IDENTIFIER); fTokenizer.SetCommandMode(true); bool ambiguous; debugger_command* command = find_debugger_command(token.string, true, ambiguous); if (command == NULL) { if (ambiguous) { snprintf(sTempBuffer, sizeof(sTempBuffer), "Ambiguous command \"%s\". Use tab completion or enter " "\"help %s\" get a list of matching commands.\n", token.string, token.string); } else { snprintf(sTempBuffer, sizeof(sTempBuffer), "Unknown command \"%s\". Enter \"help\" to get a list of " "all supported commands.\n", token.string); } parse_exception(sTempBuffer, -1); } // allocate temporary buffer for the argument vector char** argv = (char**)checked_malloc(kMaxArgumentCount * sizeof(char*)); int argc = 0; argv[argc++] = (char*)command->name; // get the arguments if ((command->flags & B_KDEBUG_DONT_PARSE_ARGUMENTS) != 0) { _GetUnparsedArgument(argc, argv); } else { while (fTokenizer.NextToken().type != TOKEN_END_OF_LINE) { fTokenizer.RewindToken(); if (!_ParseArgument(argc, argv)) break; } } if (segment.index > 0) { if (argc >= kMaxArgumentCount) parse_exception("too many arguments for command", 0); else argc++; } segment.command = command; segment.argc = argc; segment.argv = argv; segment.invocations = 0; }
uint64 ExpressionParser::EvaluateCommand(const char* expressionString, int& returnCode) { fTokenizer.SetTo(expressionString); // Allowed are command or assignment. A command always starts with an // identifier, an assignment either with an identifier (variable name) or // a dereferenced address. const Token& token = fTokenizer.NextToken(); uint64 value = 0; while (true) { int32 startPosition = token.position; if (token.type == TOKEN_IDENTIFIER) { fTokenizer.NextToken(); if (token.type & TOKEN_ASSIGN_FLAG) { // an assignment fTokenizer.SetPosition(startPosition); value = _ParseExpression(true); returnCode = 0; } else { // no assignment, so let's assume it's a command fTokenizer.SetPosition(startPosition); fTokenizer.SetCommandMode(true); value = _ParseCommandPipe(returnCode); } } else if (token.type == TOKEN_STAR) { // dereferenced address -- assignment fTokenizer.SetPosition(startPosition); value = _ParseExpression(true); returnCode = 0; } else parse_exception("expected command or assignment", token.position); // might be chained with ";" if (fTokenizer.NextToken().type != TOKEN_SEMICOLON) break; fTokenizer.SetCommandMode(false); fTokenizer.NextToken(); } if (token.type != TOKEN_END_OF_LINE) parse_exception("parse error", token.position); return value; }
//string big_integer::big_integer(std::string const& str) { if (str == "" || str == "0") { *this = big_integer(); } else { std::string temp = str; int cut = 0; if (temp.at(0) == '-') cut = 1; while (temp.at(cut) == '0' && cut < temp.size() - 1) temp.erase(cut, cut); if (temp == "0" || temp == "-0" || temp == "") { *this = big_integer(); return; } std::reverse(temp.begin(), temp.end()); for (int i = 0; i < temp.size() - 1; ++i) { if (!isdigit(temp[i])) { throw parse_exception("Illegal character"); } this->digits.push_back(temp[i] - 48); } if (temp[temp.size() - 1] == '-') { sign = -1; } else { sign = 1; this->digits.push_back(temp[temp.size() - 1] - 48); } } };
T read(const std::string& source, size_t& pos) { T result = readOptional<T>(source, pos); if(result == T::none) throw parse_exception(string("Expected token of type: ").append(typeid(T).name()), pos); else return result; }
void RecordParser::parse(const unsigned char * content, int content_size, RecordParseListener &listener) { ContentBuffer reader(content, content_size); reader.prepare(1); if (reader.content[reader.cursor] != 0) throw parse_exception("unsupported version"); readDocument(reader, listener); }
size_t reader<size_t>::read(Serializer& s) { size_t val = 0; size_t offs = 0; if (s.offset >= s.buffer->size()) throw parse_exception("buffer underrun"); while ((*s.buffer)[s.offset] & 0x80) { val |= ((size_t)(*s.buffer)[s.offset] & 0x7F) << offs; offs += 7; s.offset++; if (s.offset >= s.buffer->size()) throw parse_exception("buffer underrun"); } val |= (*s.buffer)[s.offset] << offs; s.offset++; return val; }
uint64 ExpressionParser::_ParseCommandPipe(int& returnCode) { debugger_command_pipe* pipe = (debugger_command_pipe*)checked_malloc( sizeof(debugger_command_pipe)); pipe->segment_count = 0; pipe->broken = false; do { if (pipe->segment_count >= MAX_DEBUGGER_COMMAND_PIPE_LENGTH) parse_exception("Pipe too long", fTokenizer.NextToken().position); debugger_command_pipe_segment& segment = pipe->segments[pipe->segment_count]; segment.index = pipe->segment_count++; _ParseCommand(segment); } while (fTokenizer.NextToken().type == TOKEN_PIPE); fTokenizer.RewindToken(); // invoke the pipe returnCode = invoke_debugger_command_pipe(pipe); debug_free(pipe); return get_debug_variable("_", 0); }
std::string reader<std::string>::read(Serializer& s) { size_t length = reader<size_t>::read(s); size_t offs = s.offset; s.offset += length; if (s.offset > s.buffer->size()) throw parse_exception("buffer underrun"); return std::string((const char *)s.buffer->data()+offs, length); }
long parse_long_str(const std::string& s) { const char* s2(s.c_str()); const long val(parse_long(s2)); if ((s2-s.c_str())!=static_cast<int>(s.length())) { parse_exception("long int",s.c_str()); } return val; }
unsigned parse_unsigned_str(const std::string& s) { const char* s2(s.c_str()); const unsigned val(parse_unsigned(s2)); if ((s2-s.c_str())!=static_cast<int>(s.length())) { parse_exception("unsigned",s.c_str()); } return val; }
size_t Defines::match(const std::string& define, const std::string& source, size_t pos) { regex r(define); smatch mres; if (regex_search(source.begin()+pos, source.end(), mres, r, regex_constants::match_continuous)) { return mres.length(); } else { throw parse_exception("pattern /" + define + "/ didn't match", pos); } }
int parse_int_str(const std::string& s) { const char* s2(s.c_str()); const int val(parse_int(s2)); if ((s2-s.c_str())!=static_cast<int>(s.length())) { parse_exception("int",s.c_str()); } return val; }
unique_ptr<Grammar> Parser::parse(std::istream& source) { std::string content((istreambuf_iterator<char>(source)), istreambuf_iterator<char>()); size_t pos = 0; try { auto result = Parser::consume<Grammar>(content, pos); if(pos < content.length()) throw parse_exception("Grammar couldn't parse complete input. Some characters are left.", pos); return result; } catch (parse_exception& e) { auto start = content.cbegin() + e.pos; auto snippetLength = std::min(std::distance(start, content.cend()), 200); string context = "Grammar parse failed near:\n"; context.append(start, start + snippetLength); throw parse_exception(e, context); } }
double parse_double_str(const std::string& s) { const char* s2(s.c_str()); const double val(parse_double(s2)); if ((s2-s.c_str())!=static_cast<int>(s.length())) { parse_exception("double",s.c_str()); } return val; }
unique_ptr<T> Parser::consume(const std::string& source, size_t& pos) { size_t localPos = pos; try { auto result = T::build(source, localPos); //if this throws an exception, pos doesn't get changed and the exception propagates upwards pos = localPos; //No exception, so update position return result; } catch (parse_exception& e) { throw parse_exception(e, string("when trying to consume ").append(typeid(T).name())); } }
uint64 ExpressionParser::_ParseAtom() { const Token& token = fTokenizer.NextToken(); if (token.type == TOKEN_END_OF_LINE) parse_exception("unexpected end of expression", token.position); if (token.type == TOKEN_CONSTANT) return token.value; if (token.type == TOKEN_IDENTIFIER) { if (!is_debug_variable_defined(token.string)) { snprintf(sTempBuffer, sizeof(sTempBuffer), "variable '%s' undefined", token.string); parse_exception(sTempBuffer, token.position); } return get_debug_variable(token.string, 0); } if (token.type == TOKEN_OPENING_PARENTHESIS) { uint64 value = _ParseExpression(); _EatToken(TOKEN_CLOSING_PARENTHESIS); return value; } // it can only be a "[ command ]" expression now fTokenizer.RewindToken(); _EatToken(TOKEN_OPENING_BRACKET); fTokenizer.SetCommandMode(true); int returnValue; uint64 value = _ParseCommandPipe(returnValue); fTokenizer.SetCommandMode(false); _EatToken(TOKEN_CLOSING_BRACKET); return value; }
static void* checked_malloc(size_t size) { void* address = debug_malloc(size); if (address == NULL) { parse_exception("out of memory for command execution", -1); return NULL; } return address; }
double parse_double_str( const std::string& s) { const char* s2(s.c_str()); const char* const s2_end(s2+s.size()); const double val(parse_double(s2,s2_end)); if (s2 != s2_end) { parse_exception("double",s.c_str()); } return val; }
uint64 ExpressionParser::EvaluateExpression(const char* expressionString) { fTokenizer.SetTo(expressionString); uint64 value = _ParseExpression(); const Token& token = fTokenizer.NextToken(); if (token.type != TOKEN_END_OF_LINE) parse_exception("parse error", token.position); return value; }
const Token& ExpressionParser::_EatToken(int32 type) { const Token& token = fTokenizer.NextToken(); if (token.type != type) { snprintf(sTempBuffer, sizeof(sTempBuffer), "expected token type '%c', " "got token '%s'", char(type & ~TOKEN_FLAGS), token.string); parse_exception(sTempBuffer, token.position); } return token; }
const Token& _QuotedString() { const char* begin = fCurrentChar++; int32 length = 0; while (*fCurrentChar != '\0' && *fCurrentChar != '"') { char c = *fCurrentChar; fCurrentChar++; if (c == '\\') { // an escaped char c = *fCurrentChar; fCurrentChar++; if (c == '\0') break; } if ((size_t)length >= sizeof(fCurrentToken.string) - 1) { parse_exception("quoted string too long", begin - fString); } fCurrentToken.string[length++] = c; } if (*fCurrentChar == '\0') { parse_exception("unexpected end of line while " "parsing quoted string", begin - fString); } fCurrentChar++; fCurrentToken.string[length] = '\0'; fCurrentToken.value = 0; fCurrentToken.type = TOKEN_STRING; fCurrentToken.position = begin - fString; return fCurrentToken; }
bool ExpressionParser::_ParseArgument(int& argc, char** argv) { const Token& token = fTokenizer.NextToken(); switch (token.type) { case TOKEN_OPENING_PARENTHESIS: { // this starts an expression fTokenizer.SetCommandMode(false); uint64 value = _ParseExpression(); fTokenizer.SetCommandMode(true); _EatToken(TOKEN_CLOSING_PARENTHESIS); snprintf(sTempBuffer, sizeof(sTempBuffer), "%" B_PRIu64, value); _AddArgument(argc, argv, sTempBuffer); return true; } case TOKEN_OPENING_BRACKET: { // this starts a sub command int returnValue; uint64 value = _ParseCommandPipe(returnValue); _EatToken(TOKEN_CLOSING_BRACKET); snprintf(sTempBuffer, sizeof(sTempBuffer), "%" B_PRIu64, value); _AddArgument(argc, argv, sTempBuffer); return true; } case TOKEN_STRING: case TOKEN_UNKNOWN: _AddArgument(argc, argv, token.string); return true; case TOKEN_CLOSING_PARENTHESIS: case TOKEN_CLOSING_BRACKET: case TOKEN_PIPE: case TOKEN_SEMICOLON: // those don't belong to us fTokenizer.RewindToken(); return false; default: { snprintf(sTempBuffer, sizeof(sTempBuffer), "unexpected token " "\"%s\"", token.string); parse_exception(sTempBuffer, token.position); return false; } } }
unsigned parse_unsigned(const char*& s) { static const int base(10); errno = 0; char* endptr; const unsigned long val(strtoul(s, &endptr, base)); if ((errno == ERANGE && (val == ULONG_MAX || val == 0)) || (errno != 0 && val == 0) || (endptr == s)) { parse_exception("unsigned long",s); } if (val > std::numeric_limits<unsigned>::max()) { parse_exception("unsigned",s); } s = endptr; return static_cast<unsigned>(val); }
int parse_int(const char*& s) { const char* endptr(s); const long val(parse_long(endptr)); if (val > std::numeric_limits<int>::max()) { parse_exception("int",s); } s = endptr; return static_cast<int>(val); }
double parse_double(const char*& s) { errno = 0; char* endptr; const double val(strtod(s, &endptr)); if ((errno == ERANGE) || (endptr == s)) { parse_exception("double",s); } s = endptr; return val; }
void ExpressionParser::_AddArgument(int& argc, char** argv, const char* argument, int32 length) { if (argc == kMaxArgumentCount) parse_exception("too many arguments for command", 0); if (length < 0) length = strlen(argument); length++; char* buffer = (char*)checked_malloc(length); strlcpy(buffer, argument, length); argv[argc++] = buffer; }
long parse_long(const char*& s) { static const int base(10); errno = 0; char* endptr; const long val(strtol(s, &endptr, base)); if ((errno == ERANGE && (val == LONG_MIN || val == LONG_MAX)) || (errno != 0 && val == 0) || (endptr == s)) { parse_exception("long int",s); } s = endptr; return val; }
double parse_double( const char*& s, const char* s_end) { double val; const char* s_start(s); if (s_end == NULL) s_end = s + strlen(s); bool isPass(boost::spirit::qi::parse(s, s_end, boost::spirit::double_, val)); if (isPass) { isPass = (s_start != s); } if (!isPass) { parse_exception("double", s_start); } return val; }