/* * File: ElftosbAST.cpp * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #include "ElftosbAST.h" #include #include #include #include "ElftosbErrors.h" #include "format_string.h" using namespace elftosb; #pragma mark = ASTNode = void ASTNode::printTree(int indent) const { printIndent(indent); printf("%s\n", nodeName().c_str()); } void ASTNode::printIndent(int indent) const { int i; for (i = 0; i < indent; ++i) { printf(" "); } } void ASTNode::setLocation(token_loc_t &first, token_loc_t &last) { m_location.m_firstLine = first.m_firstLine; m_location.m_lastLine = last.m_lastLine; } void ASTNode::setLocation(ASTNode *first, ASTNode *last) { m_location.m_firstLine = first->getLocation().m_firstLine; m_location.m_lastLine = last->getLocation().m_lastLine; } #pragma mark = ListASTNode = ListASTNode::ListASTNode(const ListASTNode &other) : ASTNode(other) , m_list() { // deep copy each item of the original's list const_iterator it = other.begin(); for (; it != other.end(); ++it) { m_list.push_back((*it)->clone()); } } //! Deletes child node in the list. //! ListASTNode::~ListASTNode() { iterator it = begin(); for (; it != end(); it++) { delete *it; } } //! If \a node is NULL then the list is left unmodified. //! //! The list node's location is automatically updated after the node is added by a call //! to updateLocation(). void ListASTNode::appendNode(ASTNode *node) { if (node) { m_list.push_back(node); updateLocation(); } } void ListASTNode::printTree(int indent) const { ASTNode::printTree(indent); int n = 0; const_iterator it = begin(); for (; it != end(); it++, n++) { printIndent(indent + 1); printf("%d:\n", n); (*it)->printTree(indent + 2); } } void ListASTNode::updateLocation() { token_loc_t current = { 0 }; const_iterator it = begin(); for (; it != end(); it++) { const ASTNode *node = *it; const token_loc_t &loc = node->getLocation(); // handle first node if (current.m_firstLine == 0) { current = loc; continue; } if (loc.m_firstLine < current.m_firstLine) { current.m_firstLine = loc.m_firstLine; } if (loc.m_lastLine > current.m_lastLine) { current.m_lastLine = loc.m_lastLine; } } setLocation(current); } #pragma mark = CommandFileASTNode = CommandFileASTNode::CommandFileASTNode() : ASTNode() , m_options() , m_constants() , m_sources() , m_sections() { } CommandFileASTNode::CommandFileASTNode(const CommandFileASTNode &other) : ASTNode(other) , m_options() , m_constants() , m_sources() , m_sections() { m_options = dynamic_cast(other.m_options->clone()); m_constants = dynamic_cast(other.m_constants->clone()); m_sources = dynamic_cast(other.m_sources->clone()); m_sections = dynamic_cast(other.m_sections->clone()); } void CommandFileASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("options:\n"); if (m_options) m_options->printTree(indent + 2); printIndent(indent + 1); printf("constants:\n"); if (m_constants) m_constants->printTree(indent + 2); printIndent(indent + 1); printf("sources:\n"); if (m_sources) m_sources->printTree(indent + 2); printIndent(indent + 1); printf("sections:\n"); if (m_sections) m_sections->printTree(indent + 2); } #pragma mark = ExprASTNode = int_size_t ExprASTNode::resultIntSize(int_size_t a, int_size_t b) { int_size_t result; switch (a) { case kWordSize: result = kWordSize; break; case kHalfWordSize: if (b == kWordSize) { result = kWordSize; } else { result = kHalfWordSize; } break; case kByteSize: if (b == kWordSize) { result = kWordSize; } else if (b == kHalfWordSize) { result = kHalfWordSize; } else { result = kByteSize; } break; } return result; } #pragma mark = IntConstExprASTNode = IntConstExprASTNode::IntConstExprASTNode(const IntConstExprASTNode &other) : ExprASTNode(other) , m_value(other.m_value) , m_size(other.m_size) { } void IntConstExprASTNode::printTree(int indent) const { printIndent(indent); char sizeChar = '?'; switch (m_size) { case kWordSize: sizeChar = 'w'; break; case kHalfWordSize: sizeChar = 'h'; break; case kByteSize: sizeChar = 'b'; break; } printf("%s(%d:%c)\n", nodeName().c_str(), m_value, sizeChar); } #pragma mark = VariableExprASTNode = VariableExprASTNode::VariableExprASTNode(const VariableExprASTNode &other) : ExprASTNode(other) , m_variable() { m_variable = new std::string(*other.m_variable); } void VariableExprASTNode::printTree(int indent) const { printIndent(indent); printf("%s(%s)\n", nodeName().c_str(), m_variable->c_str()); } ExprASTNode *VariableExprASTNode::reduce(EvalContext &context) { if (!context.isVariableDefined(*m_variable)) { throw std::runtime_error( format_string("line %d: undefined variable '%s'", getFirstLine(), m_variable->c_str())); } uint32_t value = context.getVariableValue(*m_variable); int_size_t size = context.getVariableSize(*m_variable); return new IntConstExprASTNode(value, size); } #pragma mark = SymbolRefExprASTNode = SymbolRefExprASTNode::SymbolRefExprASTNode(const SymbolRefExprASTNode &other) : ExprASTNode(other) , m_symbol(NULL) { if (other.m_symbol) { m_symbol = dynamic_cast(other.m_symbol->clone()); } } void SymbolRefExprASTNode::printTree(int indent) const { } ExprASTNode *SymbolRefExprASTNode::reduce(EvalContext &context) { EvalContext::SourceFileManager *manager = context.getSourceFileManager(); if (!manager) { throw std::runtime_error("no source manager available"); } if (!m_symbol) { throw semantic_error("no symbol provided"); } // Get the name of the symbol std::string *symbolName = m_symbol->getSymbolName(); // if (!symbolName) // { // throw semantic_error(format_string("line %d: no symbol name provided", getFirstLine())); // } // Get the source file. std::string *sourceName = m_symbol->getSource(); SourceFile *sourceFile; if (sourceName) { sourceFile = manager->getSourceFile(*sourceName); if (!sourceFile) { throw semantic_error( format_string("line %d: no source file named %s", getFirstLine(), sourceName->c_str())); } } else { sourceFile = manager->getDefaultSourceFile(); if (!sourceFile) { throw semantic_error(format_string("line %d: no default source file is set", getFirstLine())); } } // open the file if it hasn't already been if (!sourceFile->isOpen()) { sourceFile->open(); } // Make sure the source file supports symbols before going any further if (symbolName && !sourceFile->supportsNamedSymbols()) { throw semantic_error(format_string("line %d: source file %s does not support symbols", getFirstLine(), sourceFile->getPath().c_str())); } if (!symbolName && !sourceFile->hasEntryPoint()) { throw semantic_error(format_string("line %d: source file %s does not have an entry point", getFirstLine(), sourceFile->getPath().c_str())); } // Returns a const expr node with the symbol's value. uint32_t value; if (symbolName) { value = sourceFile->getSymbolValue(*symbolName); } else { value = sourceFile->getEntryPointAddress(); } return new IntConstExprASTNode(value); } #pragma mark = NegativeExprASTNode = NegativeExprASTNode::NegativeExprASTNode(const NegativeExprASTNode &other) : ExprASTNode(other) , m_expr() { m_expr = dynamic_cast(other.m_expr->clone()); } void NegativeExprASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); if (m_expr) m_expr->printTree(indent + 1); } ExprASTNode *NegativeExprASTNode::reduce(EvalContext &context) { if (!m_expr) { return this; } m_expr = m_expr->reduce(context); IntConstExprASTNode *intConst = dynamic_cast(m_expr.get()); if (intConst) { int32_t value = -(int32_t)intConst->getValue(); return new IntConstExprASTNode((uint32_t)value, intConst->getSize()); } else { return this; } } #pragma mark = BooleanNotExprASTNode = BooleanNotExprASTNode::BooleanNotExprASTNode(const BooleanNotExprASTNode &other) : ExprASTNode(other) , m_expr() { m_expr = dynamic_cast(other.m_expr->clone()); } void BooleanNotExprASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); if (m_expr) m_expr->printTree(indent + 1); } ExprASTNode *BooleanNotExprASTNode::reduce(EvalContext &context) { if (!m_expr) { return this; } m_expr = m_expr->reduce(context); IntConstExprASTNode *intConst = dynamic_cast(m_expr.get()); if (intConst) { int32_t value = !((int32_t)intConst->getValue()); return new IntConstExprASTNode((uint32_t)value, intConst->getSize()); } else { throw semantic_error( format_string("line %d: expression did not evaluate to an integer", m_expr->getFirstLine())); } } #pragma mark = SourceFileFunctionASTNode = SourceFileFunctionASTNode::SourceFileFunctionASTNode(const SourceFileFunctionASTNode &other) : ExprASTNode(other) , m_functionName() , m_sourceFile() { m_functionName = new std::string(*other.m_functionName); m_sourceFile = new std::string(*other.m_sourceFile); } void SourceFileFunctionASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); printIndent(indent + 1); // for some stupid reason the msft C++ compiler barfs on the following line if the ".get()" parts are remove, // even though the first line of reduce() below has the same expression, just in parentheses. stupid compiler. if (m_functionName.get() && m_sourceFile.get()) { printf("%s ( %s )\n", m_functionName->c_str(), m_sourceFile->c_str()); } } ExprASTNode *SourceFileFunctionASTNode::reduce(EvalContext &context) { if (!(m_functionName && m_sourceFile)) { throw std::runtime_error("unset function name or source file"); } // Get source file manager from evaluation context. This will be the // conversion controller itself. EvalContext::SourceFileManager *mgr = context.getSourceFileManager(); if (!mgr) { throw std::runtime_error("source file manager is not set"); } // Perform function uint32_t functionResult = 0; if (*m_functionName == "exists") { functionResult = static_cast(mgr->hasSourceFile(*m_sourceFile)); } // Return function result as an expression node return new IntConstExprASTNode(functionResult); } #pragma mark = DefinedOperatorASTNode = DefinedOperatorASTNode::DefinedOperatorASTNode(const DefinedOperatorASTNode &other) : ExprASTNode(other) , m_constantName() { m_constantName = new std::string(*other.m_constantName); } void DefinedOperatorASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); printIndent(indent + 1); if (m_constantName) { printf("defined ( %s )\n", m_constantName->c_str()); } } ExprASTNode *DefinedOperatorASTNode::reduce(EvalContext &context) { assert(m_constantName); // Return function result as an expression node return new IntConstExprASTNode(context.isVariableDefined(m_constantName) ? 1 : 0); } #pragma mark = SizeofOperatorASTNode = SizeofOperatorASTNode::SizeofOperatorASTNode(const SizeofOperatorASTNode &other) : ExprASTNode(other) , m_constantName() , m_symbol() { m_constantName = new std::string(*other.m_constantName); m_symbol = dynamic_cast(other.m_symbol->clone()); } void SizeofOperatorASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); printIndent(indent + 1); if (m_constantName) { printf("sizeof: %s\n", m_constantName->c_str()); } else if (m_symbol) { printf("sizeof:\n"); m_symbol->printTree(indent + 2); } } ExprASTNode *SizeofOperatorASTNode::reduce(EvalContext &context) { // One or the other must be defined. assert(m_constantName || m_symbol); EvalContext::SourceFileManager *manager = context.getSourceFileManager(); assert(manager); unsigned sizeInBytes = 0; SourceFile *sourceFile; if (m_symbol) { // Get the symbol name. std::string *symbolName = m_symbol->getSymbolName(); assert(symbolName); // Get the source file, using the default if one is not specified. std::string *sourceName = m_symbol->getSource(); if (sourceName) { sourceFile = manager->getSourceFile(*sourceName); if (!sourceFile) { throw semantic_error( format_string("line %d: invalid source file: %s", getFirstLine(), sourceName->c_str())); } } else { sourceFile = manager->getDefaultSourceFile(); if (!sourceFile) { throw semantic_error(format_string("line %d: no default source file is set", getFirstLine())); } } // open the file if it hasn't already been if (!sourceFile->isOpen()) { sourceFile->open(); } // Make sure the source file supports symbols before going any further if (!sourceFile->supportsNamedSymbols()) { throw semantic_error(format_string("line %d: source file %s does not support symbols", getFirstLine(), sourceFile->getPath().c_str())); } // Get the size of the symbol. if (sourceFile->hasSymbol(*symbolName)) { sizeInBytes = sourceFile->getSymbolSize(*symbolName); } } else if (m_constantName) { // See if the "constant" is really a constant or if it's a source name. if (manager->hasSourceFile(m_constantName)) { sourceFile = manager->getSourceFile(m_constantName); if (sourceFile) { sizeInBytes = sourceFile->getSize(); } } else { // Regular constant. if (!context.isVariableDefined(*m_constantName)) { throw semantic_error(format_string("line %d: cannot get size of undefined constant %s", getFirstLine(), m_constantName->c_str())); } int_size_t intSize = context.getVariableSize(*m_constantName); switch (intSize) { case kWordSize: sizeInBytes = sizeof(uint32_t); break; case kHalfWordSize: sizeInBytes = sizeof(uint16_t); break; case kByteSize: sizeInBytes = sizeof(uint8_t); break; } } } // Return function result as an expression node return new IntConstExprASTNode(sizeInBytes); } #pragma mark = BinaryOpExprASTNode = BinaryOpExprASTNode::BinaryOpExprASTNode(const BinaryOpExprASTNode &other) : ExprASTNode(other) , m_left() , m_op(other.m_op) , m_right() { m_left = dynamic_cast(other.m_left->clone()); m_right = dynamic_cast(other.m_right->clone()); } void BinaryOpExprASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); printIndent(indent + 1); printf("left:\n"); if (m_left) m_left->printTree(indent + 2); printIndent(indent + 1); printf("op: %s\n", getOperatorName().c_str()); printIndent(indent + 1); printf("right:\n"); if (m_right) m_right->printTree(indent + 2); } std::string BinaryOpExprASTNode::getOperatorName() const { switch (m_op) { case kAdd: return "+"; case kSubtract: return "-"; case kMultiply: return "*"; case kDivide: return "/"; case kModulus: return "%"; case kPower: return "**"; case kBitwiseAnd: return "&"; case kBitwiseOr: return "|"; case kBitwiseXor: return "^"; case kShiftLeft: return "<<"; case kShiftRight: return ">>"; case kLessThan: return "<"; case kGreaterThan: return ">"; case kLessThanEqual: return "<="; case kGreaterThanEqual: return ">"; case kEqual: return "=="; case kNotEqual: return "!="; case kBooleanAnd: return "&&"; case kBooleanOr: return "||"; } return "???"; } //! \todo Fix power operator under windows!!! //! ExprASTNode *BinaryOpExprASTNode::reduce(EvalContext &context) { if (!m_left || !m_right) { return this; } IntConstExprASTNode *leftIntConst = NULL; IntConstExprASTNode *rightIntConst = NULL; uint32_t leftValue; uint32_t rightValue; uint32_t result = 0; // Always reduce the left hand side. m_left = m_left->reduce(context); leftIntConst = dynamic_cast(m_left.get()); if (!leftIntConst) { throw semantic_error( format_string("left hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str())); } leftValue = leftIntConst->getValue(); // Boolean && and || operators are handled separately so that we can perform // short-circuit evaluation. if (m_op == kBooleanAnd || m_op == kBooleanOr) { // Reduce right hand side only if required to evaluate the boolean operator. if ((m_op == kBooleanAnd && leftValue != 0) || (m_op == kBooleanOr && leftValue == 0)) { m_right = m_right->reduce(context); rightIntConst = dynamic_cast(m_right.get()); if (!rightIntConst) { throw semantic_error(format_string("right hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str())); } rightValue = rightIntConst->getValue(); // Perform the boolean operation. switch (m_op) { case kBooleanAnd: result = leftValue && rightValue; break; case kBooleanOr: result = leftValue && rightValue; break; default:; } } else if (m_op == kBooleanAnd) { // The left hand side is false, so the && operator's result must be false // without regard to the right hand side. result = 0; } else if (m_op == kBooleanOr) { // The left hand value is true so the || result is automatically true. result = 1; } } else { // Reduce right hand side always for most operators. m_right = m_right->reduce(context); rightIntConst = dynamic_cast(m_right.get()); if (!rightIntConst) { throw semantic_error(format_string("right hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str())); } rightValue = rightIntConst->getValue(); switch (m_op) { case kAdd: result = leftValue + rightValue; break; case kSubtract: result = leftValue - rightValue; break; case kMultiply: result = leftValue * rightValue; break; case kDivide: result = leftValue / rightValue; break; case kModulus: result = leftValue % rightValue; break; case kPower: #ifdef WIN32 result = 0; #else result = lroundf(powf(float(leftValue), float(rightValue))); #endif break; case kBitwiseAnd: result = leftValue & rightValue; break; case kBitwiseOr: result = leftValue | rightValue; break; case kBitwiseXor: result = leftValue ^ rightValue; break; case kShiftLeft: result = leftValue << rightValue; break; case kShiftRight: result = leftValue >> rightValue; break; case kLessThan: result = leftValue < rightValue; break; case kGreaterThan: result = leftValue > rightValue; break; case kLessThanEqual: result = leftValue <= rightValue; break; case kGreaterThanEqual: result = leftValue >= rightValue; break; case kEqual: result = leftValue == rightValue; break; case kNotEqual: result = leftValue != rightValue; break; default:; } } // Create the result value. int_size_t resultSize; if (leftIntConst && rightIntConst) { resultSize = resultIntSize(leftIntConst->getSize(), rightIntConst->getSize()); } else if (leftIntConst) { resultSize = leftIntConst->getSize(); } else { // This shouldn't really be possible, but just in case. resultSize = kWordSize; } return new IntConstExprASTNode(result, resultSize); } #pragma mark = IntSizeExprASTNode = IntSizeExprASTNode::IntSizeExprASTNode(const IntSizeExprASTNode &other) : ExprASTNode(other) , m_expr() , m_size(other.m_size) { m_expr = dynamic_cast(other.m_expr->clone()); } void IntSizeExprASTNode::printTree(int indent) const { ExprASTNode::printTree(indent); char sizeChar = '?'; switch (m_size) { case kWordSize: sizeChar = 'w'; break; case kHalfWordSize: sizeChar = 'h'; break; case kByteSize: sizeChar = 'b'; break; } printIndent(indent + 1); printf("size: %c\n", sizeChar); printIndent(indent + 1); printf("expr:\n"); if (m_expr) m_expr->printTree(indent + 2); } ExprASTNode *IntSizeExprASTNode::reduce(EvalContext &context) { if (!m_expr) { return this; } m_expr = m_expr->reduce(context); IntConstExprASTNode *intConst = dynamic_cast(m_expr.get()); if (!intConst) { return this; } return new IntConstExprASTNode(intConst->getValue(), m_size); } #pragma mark = ExprConstASTNode = ExprConstASTNode::ExprConstASTNode(const ExprConstASTNode &other) : ConstASTNode(other) , m_expr() { m_expr = dynamic_cast(other.m_expr->clone()); } void ExprConstASTNode::printTree(int indent) const { ConstASTNode::printTree(indent); if (m_expr) m_expr->printTree(indent + 1); } #pragma mark = StringConstASTNode = StringConstASTNode::StringConstASTNode(const StringConstASTNode &other) : ConstASTNode(other) , m_value() { m_value = new std::string(other.m_value); } void StringConstASTNode::printTree(int indent) const { printIndent(indent); printf("%s(%s)\n", nodeName().c_str(), m_value->c_str()); } #pragma mark = BlobConstASTNode = BlobConstASTNode::BlobConstASTNode(const BlobConstASTNode &other) : ConstASTNode(other) , m_blob() { m_blob = new Blob(*other.m_blob); } void BlobConstASTNode::printTree(int indent) const { printIndent(indent); const uint8_t *dataPtr = m_blob->getData(); unsigned dataLen = m_blob->getLength(); printf("%s(%p:%d)\n", nodeName().c_str(), dataPtr, dataLen); } #pragma mark = IVTConstASTNode = IVTConstASTNode::IVTConstASTNode(const IVTConstASTNode &other) : ConstASTNode(other) , m_fields() { m_fields = dynamic_cast(other.m_fields->clone()); } void IVTConstASTNode::printTree(int indent) const { printIndent(indent); printf("%s:\n", nodeName().c_str()); if (m_fields) { m_fields->printTree(indent + 1); } } #pragma mark = AssignmentASTNode = AssignmentASTNode::AssignmentASTNode(const AssignmentASTNode &other) : ASTNode(other) , m_ident() , m_value() { m_ident = new std::string(*other.m_ident); m_value = dynamic_cast(other.m_value->clone()); } void AssignmentASTNode::printTree(int indent) const { printIndent(indent); printf("%s(%s)\n", nodeName().c_str(), m_ident->c_str()); if (m_value) m_value->printTree(indent + 1); } #pragma mark = SourceDefASTNode = SourceDefASTNode::SourceDefASTNode(const SourceDefASTNode &other) : ASTNode(other) , m_name() { m_name = new std::string(*other.m_name); } #pragma mark = PathSourceDefASTNode = PathSourceDefASTNode::PathSourceDefASTNode(const PathSourceDefASTNode &other) : SourceDefASTNode(other) , m_path() { m_path = new std::string(*other.m_path); } void PathSourceDefASTNode::printTree(int indent) const { SourceDefASTNode::printTree(indent); printIndent(indent + 1); printf("path: %s\n", m_path->c_str()); printIndent(indent + 1); printf("attributes:\n"); if (m_attributes) { m_attributes->printTree(indent + 2); } } #pragma mark = ExternSourceDefASTNode = ExternSourceDefASTNode::ExternSourceDefASTNode(const ExternSourceDefASTNode &other) : SourceDefASTNode(other) , m_expr() { m_expr = dynamic_cast(other.m_expr->clone()); } void ExternSourceDefASTNode::printTree(int indent) const { SourceDefASTNode::printTree(indent); printIndent(indent + 1); printf("expr:\n"); if (m_expr) m_expr->printTree(indent + 2); printIndent(indent + 1); printf("attributes:\n"); if (m_attributes) { m_attributes->printTree(indent + 2); } } #pragma mark = SectionContentsASTNode = SectionContentsASTNode::SectionContentsASTNode(const SectionContentsASTNode &other) : ASTNode(other) , m_sectionExpr() { m_sectionExpr = dynamic_cast(other.m_sectionExpr->clone()); } void SectionContentsASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("section#:\n"); if (m_sectionExpr) m_sectionExpr->printTree(indent + 2); } #pragma mark = DataSectionContentsASTNode = DataSectionContentsASTNode::DataSectionContentsASTNode(const DataSectionContentsASTNode &other) : SectionContentsASTNode(other) , m_contents() { m_contents = dynamic_cast(other.m_contents->clone()); } void DataSectionContentsASTNode::printTree(int indent) const { SectionContentsASTNode::printTree(indent); if (m_contents) { m_contents->printTree(indent + 1); } } #pragma mark = BootableSectionContentsASTNode = BootableSectionContentsASTNode::BootableSectionContentsASTNode(const BootableSectionContentsASTNode &other) : SectionContentsASTNode(other) , m_statements() { m_statements = dynamic_cast(other.m_statements->clone()); } void BootableSectionContentsASTNode::printTree(int indent) const { SectionContentsASTNode::printTree(indent); printIndent(indent + 1); printf("statements:\n"); if (m_statements) m_statements->printTree(indent + 2); } #pragma mark = KeyblobEntryASTNode = KeyblobEntryASTNode::KeyblobEntryASTNode(const KeyblobEntryASTNode &other) : ConstASTNode(other) , m_fields() { m_fields = dynamic_cast(other.m_fields->clone()); } void KeyblobEntryASTNode::printTree(int indent) const { ConstASTNode::printTree(indent); printIndent(indent + 1); printf("fields:\n"); if (m_fields) m_fields->printTree(indent + 2); } #pragma mark = IfStatementASTNode = //! \warning Be careful; this method could enter an infinite loop if m_nextIf feeds //! back onto itself. m_nextIf must be NULL at some point down the next if list. IfStatementASTNode::IfStatementASTNode(const IfStatementASTNode &other) : StatementASTNode() , m_conditionExpr() , m_ifStatements() , m_nextIf() , m_elseStatements() { m_conditionExpr = dynamic_cast(other.m_conditionExpr->clone()); m_ifStatements = dynamic_cast(other.m_ifStatements->clone()); m_nextIf = dynamic_cast(other.m_nextIf->clone()); m_elseStatements = dynamic_cast(other.m_elseStatements->clone()); } #pragma mark = ModeStatementASTNode = ModeStatementASTNode::ModeStatementASTNode(const ModeStatementASTNode &other) : StatementASTNode(other) , m_modeExpr() { m_modeExpr = dynamic_cast(other.m_modeExpr->clone()); } void ModeStatementASTNode::printTree(int indent) const { StatementASTNode::printTree(indent); printIndent(indent + 1); printf("mode:\n"); if (m_modeExpr) m_modeExpr->printTree(indent + 2); } #pragma mark = EraseStatementASTNode = EraseStatementASTNode::EraseStatementASTNode(const EraseStatementASTNode &other) : StatementASTNode(other) , m_doEraseAll(other.m_doEraseAll) , m_doEraseAllUnsecure(other.m_doEraseAllUnsecure) , m_memOption() , m_rangeExpr() { m_rangeExpr = dynamic_cast(other.m_rangeExpr->clone()); m_memOption = dynamic_cast(other.m_memOption->clone()); } void EraseStatementASTNode::printTree(int indent) const { printIndent(indent); printf("%s%s%s\n", nodeName().c_str(), (m_doEraseAll ? "/ALL" : ""), (m_doEraseAllUnsecure ? "/UNSEC" : "")); printIndent(indent + 1); printf("range:\n"); if (m_rangeExpr) m_rangeExpr->printTree(indent + 2); printIndent(indent + 1); printf("mem option:\n"); if (m_memOption) m_memOption->printTree(indent + 2); } #pragma mark = MessageStatementASTNode = MessageStatementASTNode::MessageStatementASTNode(const MessageStatementASTNode &other) : StatementASTNode(other) , m_type(other.m_type) , m_message() { m_message = new std::string(*other.m_message); } void MessageStatementASTNode::printTree(int indent) const { StatementASTNode::printTree(indent); printIndent(indent + 1); printf("%s: %s\n", getTypeName(), m_message->c_str()); } const char *MessageStatementASTNode::getTypeName() const { switch (m_type) { case kInfo: return "info"; case kWarning: return "warning"; case kError: return "error"; } return "unknown"; } #pragma mark = LoadStatementASTNode = LoadStatementASTNode::LoadStatementASTNode(const LoadStatementASTNode &other) : StatementASTNode(other) , m_data() , m_target() , m_loadOption() { m_data = other.m_data->clone(); m_target = other.m_target->clone(); m_loadOption = dynamic_cast(other.m_loadOption->clone()); } void LoadStatementASTNode::printTree(int indent) const { StatementASTNode::printTree(indent); printIndent(indent + 1); printf("data:\n"); if (m_data) m_data->printTree(indent + 2); printIndent(indent + 1); printf("target:\n"); if (m_target) m_target->printTree(indent + 2); printIndent(indent + 1); printf("load option:\n"); if (m_loadOption) m_loadOption->printTree(indent + 2); } #pragma mark = CallStatementASTNode = CallStatementASTNode::CallStatementASTNode(const CallStatementASTNode &other) : StatementASTNode(other) , m_type(other.m_type) , m_target() , m_arg() { m_target = other.m_target->clone(); m_arg = other.m_arg->clone(); m_stackPointer = other.m_stackPointer->clone(); } void CallStatementASTNode::printTree(int indent) const { printIndent(indent); printf("%s%s%s\n", nodeName().c_str(), (m_type == kCallType ? "call" : "jump"), (m_isHAB ? "/HAB" : "")); printIndent(indent + 1); printf("target:\n"); if (m_target) m_target->printTree(indent + 2); printIndent(indent + 1); printf("arg:\n"); if (m_arg) m_arg->printTree(indent + 2); printIndent(indent + 1); printf("sp:\n"); if (m_stackPointer) m_stackPointer->printTree(indent + 2); } #pragma mark = ResetStatementASTNode = void ResetStatementASTNode::printTree(int indent) const { StatementASTNode::printTree(indent); } #pragma mark = MemEnableStatementASTNode = MemEnableStatementASTNode::MemEnableStatementASTNode(const MemEnableStatementASTNode &other) : StatementASTNode(other) , m_memOption() , m_rangeExpr() { m_rangeExpr = dynamic_cast(other.m_rangeExpr->clone()); m_memOption = dynamic_cast(other.m_memOption->clone()); } void MemEnableStatementASTNode::printTree(int indent) const { StatementASTNode::printTree(indent); printIndent(indent + 1); printf("range:\n"); if (m_rangeExpr) m_rangeExpr->printTree(indent + 2); printIndent(indent + 1); printf("mem option:\n"); if (m_memOption) m_memOption->printTree(indent + 2); } #pragma mark = SourceASTNode = SourceASTNode::SourceASTNode(const SourceASTNode &other) : ASTNode(other) , m_name() { m_name = new std::string(*other.m_name); } void SourceASTNode::printTree(int indent) const { printIndent(indent); printf("%s(%s)\n", nodeName().c_str(), m_name->c_str()); } #pragma mark = SectionMatchListASTNode = SectionMatchListASTNode::SectionMatchListASTNode(const SectionMatchListASTNode &other) : ASTNode(other) , m_sections() , m_source() { if (other.m_sections) { m_sections = dynamic_cast(other.m_sections->clone()); } if (other.m_source) { m_source = new std::string(*other.m_source); } } void SectionMatchListASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("sections:\n"); if (m_sections) { m_sections->printTree(indent + 2); } printIndent(indent + 1); printf("source: "); if (m_source) { printf("%s\n", m_source->c_str()); } else { printf("\n"); } } #pragma mark = SectionASTNode = SectionASTNode::SectionASTNode(const SectionASTNode &other) : ASTNode(other) , m_name() , m_source() { m_action = other.m_action; if (other.m_name) { m_name = new std::string(*other.m_name); } if (other.m_source) { m_source = new std::string(*other.m_source); } } void SectionASTNode::printTree(int indent) const { printIndent(indent); const char *actionName; switch (m_action) { case kInclude: actionName = "include"; break; case kExclude: actionName = "exclude"; break; } if (m_source) { printf("%s(%s:%s:%s)\n", nodeName().c_str(), actionName, m_name->c_str(), m_source->c_str()); } else { printf("%s(%s:%s)\n", nodeName().c_str(), actionName, m_name->c_str()); } } #pragma mark = SymbolASTNode = SymbolASTNode::SymbolASTNode(const SymbolASTNode &other) : ASTNode(other) , m_symbol() , m_source() { m_symbol = new std::string(*other.m_symbol); m_source = new std::string(*other.m_source); } void SymbolASTNode::printTree(int indent) const { printIndent(indent); const char *symbol = NULL; if (m_symbol) { symbol = m_symbol->c_str(); } const char *source = NULL; if (m_source) { source = m_source->c_str(); } printf("%s(", nodeName().c_str()); if (source) { printf("%s", source); } else { printf("."); } printf(":"); if (symbol) { printf("%s", symbol); } else { printf("."); } printf(")\n"); } #pragma mark = AddressRangeASTNode = AddressRangeASTNode::AddressRangeASTNode(const AddressRangeASTNode &other) : ASTNode(other) , m_begin() , m_end() { m_begin = other.m_begin->clone(); m_end = other.m_end->clone(); } void AddressRangeASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("begin:\n"); if (m_begin) m_begin->printTree(indent + 2); printIndent(indent + 1); printf("end:\n"); if (m_end) m_end->printTree(indent + 2); } #pragma mark = FromStatementASTNode = FromStatementASTNode::FromStatementASTNode(std::string *source, ListASTNode *statements) : StatementASTNode() , m_source(source) , m_statements(statements) { } FromStatementASTNode::FromStatementASTNode(const FromStatementASTNode &other) : StatementASTNode() , m_source() , m_statements() { m_source = new std::string(*other.m_source); m_statements = dynamic_cast(other.m_statements->clone()); } void FromStatementASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("source: "); if (m_source) printf("%s\n", m_source->c_str()); printIndent(indent + 1); printf("statements:\n"); if (m_statements) m_statements->printTree(indent + 2); } #pragma mark = EncryptStatementASTNode = EncryptStatementASTNode::EncryptStatementASTNode() : StatementASTNode() , m_statements() , m_keyblobNumberExpr() { } EncryptStatementASTNode::EncryptStatementASTNode(const EncryptStatementASTNode &other) : StatementASTNode() , m_statements() , m_keyblobNumberExpr() { m_statements = dynamic_cast(other.m_statements->clone()); m_keyblobNumberExpr = dynamic_cast(other.m_keyblobNumberExpr->clone()); } void EncryptStatementASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("Key blob Num:\n"); if (m_keyblobNumberExpr) m_keyblobNumberExpr->printTree(indent + 2); printIndent(indent + 1); printf("statements:\n"); if (m_statements) m_statements->printTree(indent + 2); } #pragma mark = KeywrapStatementASTNode = KeywrapStatementASTNode::KeywrapStatementASTNode() : StatementASTNode() , m_statements() , m_keyblobNumberExpr() { } KeywrapStatementASTNode::KeywrapStatementASTNode(const KeywrapStatementASTNode &other) : StatementASTNode() , m_statements() , m_keyblobNumberExpr() { m_statements = dynamic_cast(other.m_statements->clone()); m_keyblobNumberExpr = dynamic_cast(other.m_keyblobNumberExpr->clone()); } void KeywrapStatementASTNode::printTree(int indent) const { ASTNode::printTree(indent); printIndent(indent + 1); printf("Key blob Num:\n"); if (m_keyblobNumberExpr) m_keyblobNumberExpr->printTree(indent + 2); printIndent(indent + 1); printf("statements:\n"); if (m_statements) m_statements->printTree(indent + 2); }