189e07bf2c75e3a91abddde3219e1108c75059985jimblandy// -*- mode: c++ -*- 289e07bf2c75e3a91abddde3219e1108c75059985jimblandy 383e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 47e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// All rights reserved. 5b934bb974afdc018252e15248455c4cc7730caa0mmentovai// 67e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// Redistribution and use in source and binary forms, with or without 77e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// modification, are permitted provided that the following conditions are 87e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// met: 9b934bb974afdc018252e15248455c4cc7730caa0mmentovai// 107e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// * Redistributions of source code must retain the above copyright 117e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// notice, this list of conditions and the following disclaimer. 127e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// * Redistributions in binary form must reproduce the above 137e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// copyright notice, this list of conditions and the following disclaimer 147e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// in the documentation and/or other materials provided with the 157e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// distribution. 167e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// * Neither the name of Google Inc. nor the names of its 177e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// contributors may be used to endorse or promote products derived from 187e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// this software without specific prior written permission. 19b934bb974afdc018252e15248455c4cc7730caa0mmentovai// 207e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 217e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 227e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 237e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 247e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 257e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 267e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 277e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 287e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 297e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 307e2b64f5fd168cde31257c6ee01436bdbc8dc599mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b934bb974afdc018252e15248455c4cc7730caa0mmentovai 32b934bb974afdc018252e15248455c4cc7730caa0mmentovai// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression 33b934bb974afdc018252e15248455c4cc7730caa0mmentovai// evaluator. 34b934bb974afdc018252e15248455c4cc7730caa0mmentovai// 35b934bb974afdc018252e15248455c4cc7730caa0mmentovai// Documentation in postfix_evaluator.h. 36b934bb974afdc018252e15248455c4cc7730caa0mmentovai// 37b934bb974afdc018252e15248455c4cc7730caa0mmentovai// Author: Mark Mentovai 38b934bb974afdc018252e15248455c4cc7730caa0mmentovai 39b934bb974afdc018252e15248455c4cc7730caa0mmentovai#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ 40b934bb974afdc018252e15248455c4cc7730caa0mmentovai#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ 41b934bb974afdc018252e15248455c4cc7730caa0mmentovai 42e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include "processor/postfix_evaluator.h" 43e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek 44e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdio.h> 45b934bb974afdc018252e15248455c4cc7730caa0mmentovai 46b934bb974afdc018252e15248455c4cc7730caa0mmentovai#include <sstream> 47b934bb974afdc018252e15248455c4cc7730caa0mmentovai 48e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/memory_region.h" 4965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai#include "processor/logging.h" 50b934bb974afdc018252e15248455c4cc7730caa0mmentovai 51e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 52b934bb974afdc018252e15248455c4cc7730caa0mmentovai 53b934bb974afdc018252e15248455c4cc7730caa0mmentovaiusing std::istringstream; 54b934bb974afdc018252e15248455c4cc7730caa0mmentovaiusing std::ostringstream; 55b934bb974afdc018252e15248455c4cc7730caa0mmentovai 56b934bb974afdc018252e15248455c4cc7730caa0mmentovai 57b934bb974afdc018252e15248455c4cc7730caa0mmentovai// A small class used in Evaluate to make sure to clean up the stack 58b934bb974afdc018252e15248455c4cc7730caa0mmentovai// before returning failure. 59b934bb974afdc018252e15248455c4cc7730caa0mmentovaiclass AutoStackClearer { 60b934bb974afdc018252e15248455c4cc7730caa0mmentovai public: 6180e98391dc7ff361355e72c24c0fb222518bcdfcmmentovai explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {} 62b934bb974afdc018252e15248455c4cc7730caa0mmentovai ~AutoStackClearer() { stack_->clear(); } 63b934bb974afdc018252e15248455c4cc7730caa0mmentovai 64b934bb974afdc018252e15248455c4cc7730caa0mmentovai private: 65b934bb974afdc018252e15248455c4cc7730caa0mmentovai vector<string> *stack_; 66b934bb974afdc018252e15248455c4cc7730caa0mmentovai}; 67b934bb974afdc018252e15248455c4cc7730caa0mmentovai 68b934bb974afdc018252e15248455c4cc7730caa0mmentovai 69b934bb974afdc018252e15248455c4cc7730caa0mmentovaitemplate<typename ValueType> 70824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.orgbool PostfixEvaluator<ValueType>::EvaluateToken( 71824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org const string &token, 7289e07bf2c75e3a91abddde3219e1108c75059985jimblandy const string &expression, 7389e07bf2c75e3a91abddde3219e1108c75059985jimblandy DictionaryValidityType *assigned) { 74824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // There are enough binary operations that do exactly the same thing 75824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // (other than the specific operation, of course) that it makes sense 76824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // to share as much code as possible. 77824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org enum BinaryOperation { 78824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_NONE = 0, 79824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_ADD, 80824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_SUBTRACT, 81824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_MULTIPLY, 82824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_DIVIDE_QUOTIENT, 83824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_DIVIDE_MODULUS, 84824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BINARY_OP_ALIGN 85824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org }; 86b934bb974afdc018252e15248455c4cc7730caa0mmentovai 87824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BinaryOperation operation = BINARY_OP_NONE; 88824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (token == "+") 89824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_ADD; 90824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org else if (token == "-") 91824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_SUBTRACT; 92824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org else if (token == "*") 93824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_MULTIPLY; 94824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org else if (token == "/") 95824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_DIVIDE_QUOTIENT; 96824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org else if (token == "%") 97824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_DIVIDE_MODULUS; 98824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org else if (token == "@") 99824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operation = BINARY_OP_ALIGN; 100b934bb974afdc018252e15248455c4cc7730caa0mmentovai 101824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (operation != BINARY_OP_NONE) { 102824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Get the operands. 103824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType operand1 = ValueType(); 104824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType operand2 = ValueType(); 105824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!PopValues(&operand1, &operand2)) { 106824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Could not PopValues to get two values for binary " 107824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org "operation " << token << ": " << expression; 108824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 109824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 110b934bb974afdc018252e15248455c4cc7730caa0mmentovai 111824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Perform the operation. 112824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType result; 113824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org switch (operation) { 114824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_ADD: 115824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = operand1 + operand2; 116824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 117824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_SUBTRACT: 118824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = operand1 - operand2; 119824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 120824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_MULTIPLY: 121824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = operand1 * operand2; 122824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 123824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_DIVIDE_QUOTIENT: 124824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = operand1 / operand2; 125824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 126824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_DIVIDE_MODULUS: 127824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = operand1 % operand2; 128824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 129824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_ALIGN: 130824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org result = 131824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org operand1 & (static_cast<ValueType>(-1) ^ (operand2 - 1)); 132824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 133824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org case BINARY_OP_NONE: 134824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // This will not happen, but compilers will want a default or 135824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // BINARY_OP_NONE case. 136824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Not reached!"; 137b934bb974afdc018252e15248455c4cc7730caa0mmentovai return false; 138824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org break; 139824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 140b934bb974afdc018252e15248455c4cc7730caa0mmentovai 141824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Save the result. 142824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org PushValue(result); 143824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } else if (token == "^") { 144824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // ^ for unary dereference. Can't dereference without memory. 145824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!memory_) { 146824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Attempt to dereference without memory: " << 147824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org expression; 148824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 149824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 150b934bb974afdc018252e15248455c4cc7730caa0mmentovai 151824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType address; 152824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!PopValue(&address)) { 153824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Could not PopValue to get value to derefence: " << 154824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org expression; 155824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 156824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 157824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org 158824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType value; 159824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!memory_->GetMemoryAtAddress(address, &value)) { 160824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Could not dereference memory at address " << 161824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org HexString(address) << ": " << expression; 162824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 163824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 164824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org 165824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org PushValue(value); 166824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } else if (token == "=") { 167824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // = for assignment. 168824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org ValueType value; 169824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!PopValue(&value)) { 170824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(INFO) << "Could not PopValue to get value to assign: " << 171824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org expression; 172824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 173824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 174824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org 175824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Assignment is only meaningful when assigning into an identifier. 176824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // The identifier must name a variable, not a constant. Variables 177824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // begin with '$'. 178824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org string identifier; 179824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { 180824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " 181824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org "identifier is needed to assign " << 182824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org HexString(value) << ": " << expression; 183824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 184824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 185824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (identifier.empty() || identifier[0] != '$') { 186824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << 187824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org identifier << ": " << expression; 188824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 189824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 190824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org 191824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org (*dictionary_)[identifier] = value; 192824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (assigned) 193824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org (*assigned)[identifier] = true; 194824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } else { 195824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // The token is not an operator, it's a literal value or an identifier. 196824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Push it onto the stack as-is. Use push_back instead of PushValue 197824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // because PushValue pushes ValueType as a string, but token is already 198824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // a string. 199824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org stack_.push_back(token); 200824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } 201824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return true; 202824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org} 203b934bb974afdc018252e15248455c4cc7730caa0mmentovai 204824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.orgtemplate<typename ValueType> 205824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.orgbool PostfixEvaluator<ValueType>::EvaluateInternal( 206824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org const string &expression, 207824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org DictionaryValidityType *assigned) { 208824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Tokenize, splitting on whitespace. 209824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org istringstream stream(expression); 210824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org string token; 211824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org while (stream >> token) { 212824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // Normally, tokens are whitespace-separated, but occasionally, the 213824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // assignment operator is smashed up against the next token, i.e. 214824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // $T0 $ebp 128 + =$eip $T0 4 + ^ =$ebp $T0 ^ = 215824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // This has been observed in program strings produced by MSVS 2010 in LTO 216824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org // mode. 217824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (token.size() > 1 && token[0] == '=') { 218824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!EvaluateToken("=", expression, assigned)) { 219b934bb974afdc018252e15248455c4cc7730caa0mmentovai return false; 22065571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 221824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org 222824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org if (!EvaluateToken(token.substr(1), expression, assigned)) { 223b934bb974afdc018252e15248455c4cc7730caa0mmentovai return false; 22465571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 225824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org } else if (!EvaluateToken(token, expression, assigned)) { 226824802fd0776c5fb7d6ca861e282ab4f63de86e6mark@chromium.org return false; 227b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 228b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 229b934bb974afdc018252e15248455c4cc7730caa0mmentovai 23089e07bf2c75e3a91abddde3219e1108c75059985jimblandy return true; 23189e07bf2c75e3a91abddde3219e1108c75059985jimblandy} 23289e07bf2c75e3a91abddde3219e1108c75059985jimblandy 23389e07bf2c75e3a91abddde3219e1108c75059985jimblandytemplate<typename ValueType> 23489e07bf2c75e3a91abddde3219e1108c75059985jimblandybool PostfixEvaluator<ValueType>::Evaluate(const string &expression, 23589e07bf2c75e3a91abddde3219e1108c75059985jimblandy DictionaryValidityType *assigned) { 23689e07bf2c75e3a91abddde3219e1108c75059985jimblandy // Ensure that the stack is cleared before returning. 23789e07bf2c75e3a91abddde3219e1108c75059985jimblandy AutoStackClearer clearer(&stack_); 23889e07bf2c75e3a91abddde3219e1108c75059985jimblandy 23989e07bf2c75e3a91abddde3219e1108c75059985jimblandy if (!EvaluateInternal(expression, assigned)) 24089e07bf2c75e3a91abddde3219e1108c75059985jimblandy return false; 24189e07bf2c75e3a91abddde3219e1108c75059985jimblandy 242b934bb974afdc018252e15248455c4cc7730caa0mmentovai // If there's anything left on the stack, it indicates incomplete execution. 243b934bb974afdc018252e15248455c4cc7730caa0mmentovai // This is a failure case. If the stack is empty, evalution was complete 244b934bb974afdc018252e15248455c4cc7730caa0mmentovai // and successful. 24589e07bf2c75e3a91abddde3219e1108c75059985jimblandy if (stack_.empty()) 24689e07bf2c75e3a91abddde3219e1108c75059985jimblandy return true; 247bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com 24889e07bf2c75e3a91abddde3219e1108c75059985jimblandy BPLOG(ERROR) << "Incomplete execution: " << expression; 24989e07bf2c75e3a91abddde3219e1108c75059985jimblandy return false; 250b934bb974afdc018252e15248455c4cc7730caa0mmentovai} 251b934bb974afdc018252e15248455c4cc7730caa0mmentovai 25289e07bf2c75e3a91abddde3219e1108c75059985jimblandytemplate<typename ValueType> 25389e07bf2c75e3a91abddde3219e1108c75059985jimblandybool PostfixEvaluator<ValueType>::EvaluateForValue(const string &expression, 25489e07bf2c75e3a91abddde3219e1108c75059985jimblandy ValueType *result) { 25589e07bf2c75e3a91abddde3219e1108c75059985jimblandy // Ensure that the stack is cleared before returning. 25689e07bf2c75e3a91abddde3219e1108c75059985jimblandy AutoStackClearer clearer(&stack_); 25789e07bf2c75e3a91abddde3219e1108c75059985jimblandy 25889e07bf2c75e3a91abddde3219e1108c75059985jimblandy if (!EvaluateInternal(expression, NULL)) 25989e07bf2c75e3a91abddde3219e1108c75059985jimblandy return false; 26089e07bf2c75e3a91abddde3219e1108c75059985jimblandy 26189e07bf2c75e3a91abddde3219e1108c75059985jimblandy // A successful execution should leave exactly one value on the stack. 26289e07bf2c75e3a91abddde3219e1108c75059985jimblandy if (stack_.size() != 1) { 26389e07bf2c75e3a91abddde3219e1108c75059985jimblandy BPLOG(ERROR) << "Expression yielded bad number of results: " 26489e07bf2c75e3a91abddde3219e1108c75059985jimblandy << "'" << expression << "'"; 26589e07bf2c75e3a91abddde3219e1108c75059985jimblandy return false; 266bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com } 26789e07bf2c75e3a91abddde3219e1108c75059985jimblandy 26889e07bf2c75e3a91abddde3219e1108c75059985jimblandy return PopValue(result); 26989e07bf2c75e3a91abddde3219e1108c75059985jimblandy} 270b934bb974afdc018252e15248455c4cc7730caa0mmentovai 271b934bb974afdc018252e15248455c4cc7730caa0mmentovaitemplate<typename ValueType> 272b934bb974afdc018252e15248455c4cc7730caa0mmentovaitypename PostfixEvaluator<ValueType>::PopResult 273b934bb974afdc018252e15248455c4cc7730caa0mmentovaiPostfixEvaluator<ValueType>::PopValueOrIdentifier( 274b934bb974afdc018252e15248455c4cc7730caa0mmentovai ValueType *value, string *identifier) { 275b934bb974afdc018252e15248455c4cc7730caa0mmentovai // There needs to be at least one element on the stack to pop. 276b934bb974afdc018252e15248455c4cc7730caa0mmentovai if (!stack_.size()) 277b934bb974afdc018252e15248455c4cc7730caa0mmentovai return POP_RESULT_FAIL; 278b934bb974afdc018252e15248455c4cc7730caa0mmentovai 279b934bb974afdc018252e15248455c4cc7730caa0mmentovai string token = stack_.back(); 280b934bb974afdc018252e15248455c4cc7730caa0mmentovai stack_.pop_back(); 281b934bb974afdc018252e15248455c4cc7730caa0mmentovai 2825cf2e760b602686c9a757e3978179f47b451c111jimblandy // First, try to treat the value as a literal. Literals may have leading 2835cf2e760b602686c9a757e3978179f47b451c111jimblandy // '-' sign, and the entire remaining string must be parseable as 2845cf2e760b602686c9a757e3978179f47b451c111jimblandy // ValueType. If this isn't possible, it can't be a literal, so treat it 2855cf2e760b602686c9a757e3978179f47b451c111jimblandy // as an identifier instead. 2865cf2e760b602686c9a757e3978179f47b451c111jimblandy // 2875cf2e760b602686c9a757e3978179f47b451c111jimblandy // Some versions of the libstdc++, the GNU standard C++ library, have 2885cf2e760b602686c9a757e3978179f47b451c111jimblandy // stream extractors for unsigned integer values that permit a leading 2895cf2e760b602686c9a757e3978179f47b451c111jimblandy // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we 2905cf2e760b602686c9a757e3978179f47b451c111jimblandy // handle it explicitly here. 291b934bb974afdc018252e15248455c4cc7730caa0mmentovai istringstream token_stream(token); 292df9901a45dac4b5162943f631168296f9d05ee20jessicag.feedback@gmail.com ValueType literal = ValueType(); 2935cf2e760b602686c9a757e3978179f47b451c111jimblandy bool negative; 2945cf2e760b602686c9a757e3978179f47b451c111jimblandy if (token_stream.peek() == '-') { 2955cf2e760b602686c9a757e3978179f47b451c111jimblandy negative = true; 2965cf2e760b602686c9a757e3978179f47b451c111jimblandy token_stream.get(); 2975cf2e760b602686c9a757e3978179f47b451c111jimblandy } else { 2985cf2e760b602686c9a757e3978179f47b451c111jimblandy negative = false; 2995cf2e760b602686c9a757e3978179f47b451c111jimblandy } 300b934bb974afdc018252e15248455c4cc7730caa0mmentovai if (token_stream >> literal && token_stream.peek() == EOF) { 301b934bb974afdc018252e15248455c4cc7730caa0mmentovai if (value) { 302b934bb974afdc018252e15248455c4cc7730caa0mmentovai *value = literal; 303b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 3045cf2e760b602686c9a757e3978179f47b451c111jimblandy if (negative) 3055cf2e760b602686c9a757e3978179f47b451c111jimblandy *value = -*value; 306b934bb974afdc018252e15248455c4cc7730caa0mmentovai return POP_RESULT_VALUE; 307b934bb974afdc018252e15248455c4cc7730caa0mmentovai } else { 308b934bb974afdc018252e15248455c4cc7730caa0mmentovai if (identifier) { 309b934bb974afdc018252e15248455c4cc7730caa0mmentovai *identifier = token; 310b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 311b934bb974afdc018252e15248455c4cc7730caa0mmentovai return POP_RESULT_IDENTIFIER; 312b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 313b934bb974afdc018252e15248455c4cc7730caa0mmentovai} 314b934bb974afdc018252e15248455c4cc7730caa0mmentovai 315b934bb974afdc018252e15248455c4cc7730caa0mmentovai 316b934bb974afdc018252e15248455c4cc7730caa0mmentovaitemplate<typename ValueType> 317b934bb974afdc018252e15248455c4cc7730caa0mmentovaibool PostfixEvaluator<ValueType>::PopValue(ValueType *value) { 318df9901a45dac4b5162943f631168296f9d05ee20jessicag.feedback@gmail.com ValueType literal = ValueType(); 319b934bb974afdc018252e15248455c4cc7730caa0mmentovai string token; 320b934bb974afdc018252e15248455c4cc7730caa0mmentovai PopResult result; 321b934bb974afdc018252e15248455c4cc7730caa0mmentovai if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { 322b934bb974afdc018252e15248455c4cc7730caa0mmentovai return false; 323b934bb974afdc018252e15248455c4cc7730caa0mmentovai } else if (result == POP_RESULT_VALUE) { 324b934bb974afdc018252e15248455c4cc7730caa0mmentovai // This is the easy case. 325b934bb974afdc018252e15248455c4cc7730caa0mmentovai *value = literal; 326b934bb974afdc018252e15248455c4cc7730caa0mmentovai } else { // result == POP_RESULT_IDENTIFIER 327b934bb974afdc018252e15248455c4cc7730caa0mmentovai // There was an identifier at the top of the stack. Resolve it to a 328b934bb974afdc018252e15248455c4cc7730caa0mmentovai // value by looking it up in the dictionary. 329b934bb974afdc018252e15248455c4cc7730caa0mmentovai typename DictionaryType::const_iterator iterator = 330b934bb974afdc018252e15248455c4cc7730caa0mmentovai dictionary_->find(token); 331b934bb974afdc018252e15248455c4cc7730caa0mmentovai if (iterator == dictionary_->end()) { 332b934bb974afdc018252e15248455c4cc7730caa0mmentovai // The identifier wasn't found in the dictionary. Don't imply any 333b934bb974afdc018252e15248455c4cc7730caa0mmentovai // default value, just fail. 334bb87ebd809e4437c953e9008a73927cd7e1c05efjessicag.feedback@gmail.com BPLOG(INFO) << "Identifier " << token << " not in dictionary"; 335b934bb974afdc018252e15248455c4cc7730caa0mmentovai return false; 336b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 337b934bb974afdc018252e15248455c4cc7730caa0mmentovai 338b934bb974afdc018252e15248455c4cc7730caa0mmentovai *value = iterator->second; 339b934bb974afdc018252e15248455c4cc7730caa0mmentovai } 340b934bb974afdc018252e15248455c4cc7730caa0mmentovai 341b934bb974afdc018252e15248455c4cc7730caa0mmentovai return true; 342b934bb974afdc018252e15248455c4cc7730caa0mmentovai} 343b934bb974afdc018252e15248455c4cc7730caa0mmentovai 344b934bb974afdc018252e15248455c4cc7730caa0mmentovai 345b934bb974afdc018252e15248455c4cc7730caa0mmentovaitemplate<typename ValueType> 346b934bb974afdc018252e15248455c4cc7730caa0mmentovaibool PostfixEvaluator<ValueType>::PopValues(ValueType *value1, 347b934bb974afdc018252e15248455c4cc7730caa0mmentovai ValueType *value2) { 348b934bb974afdc018252e15248455c4cc7730caa0mmentovai return PopValue(value2) && PopValue(value1); 349b934bb974afdc018252e15248455c4cc7730caa0mmentovai} 350b934bb974afdc018252e15248455c4cc7730caa0mmentovai 351b934bb974afdc018252e15248455c4cc7730caa0mmentovai 352b934bb974afdc018252e15248455c4cc7730caa0mmentovaitemplate<typename ValueType> 353b934bb974afdc018252e15248455c4cc7730caa0mmentovaivoid PostfixEvaluator<ValueType>::PushValue(const ValueType &value) { 354b934bb974afdc018252e15248455c4cc7730caa0mmentovai ostringstream token_stream; 355b934bb974afdc018252e15248455c4cc7730caa0mmentovai token_stream << value; 356b934bb974afdc018252e15248455c4cc7730caa0mmentovai stack_.push_back(token_stream.str()); 357b934bb974afdc018252e15248455c4cc7730caa0mmentovai} 358b934bb974afdc018252e15248455c4cc7730caa0mmentovai 359b934bb974afdc018252e15248455c4cc7730caa0mmentovai 360e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 361b934bb974afdc018252e15248455c4cc7730caa0mmentovai 362b934bb974afdc018252e15248455c4cc7730caa0mmentovai 363b934bb974afdc018252e15248455c4cc7730caa0mmentovai#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ 364