/* * 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; igetLocation().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())); } } // 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; } } 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; } } // 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 = 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 = 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_isDCDLoad(other.m_isDCDLoad) { m_data = other.m_data->clone(); m_target = other.m_target->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); } #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(); } 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); } #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); }