--- /dev/null
+/*
+ * File: ElftosbAST.cpp
+ *
+ * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
+ * See included license file for license details.
+ */
+
+#include "ElftosbAST.h"
+#include <stdexcept>
+#include <math.h>
+#include <assert.h>
+#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<ListASTNode*>(other.m_options->clone());
+ m_constants = dynamic_cast<ListASTNode*>(other.m_constants->clone());
+ m_sources = dynamic_cast<ListASTNode*>(other.m_sources->clone());
+ m_sections = dynamic_cast<ListASTNode*>(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<SymbolASTNode*>(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<ExprASTNode*>(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<IntConstExprASTNode*>(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<ExprASTNode*>(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<IntConstExprASTNode*>(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<uint32_t>(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<SymbolASTNode*>(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<ExprASTNode*>(other.m_left->clone());
+ m_right = dynamic_cast<ExprASTNode*>(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<IntConstExprASTNode*>(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<IntConstExprASTNode*>(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<IntConstExprASTNode*>(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<ExprASTNode*>(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<IntConstExprASTNode*>(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<ExprASTNode*>(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<ListASTNode*>(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<ConstASTNode*>(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<ExprASTNode*>(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<ExprASTNode*>(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<ASTNode*>(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<ListASTNode*>(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<ExprASTNode*>(other.m_conditionExpr->clone());
+ m_ifStatements = dynamic_cast<ListASTNode*>(other.m_ifStatements->clone());
+ m_nextIf = dynamic_cast<IfStatementASTNode*>(other.m_nextIf->clone());
+ m_elseStatements = dynamic_cast<ListASTNode*>(other.m_elseStatements->clone());
+}
+
+#pragma mark = ModeStatementASTNode =
+
+ModeStatementASTNode::ModeStatementASTNode(const ModeStatementASTNode & other)
+: StatementASTNode(other), m_modeExpr()
+{
+ m_modeExpr = dynamic_cast<ExprASTNode*>(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<ListASTNode *>(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: ", m_source->c_str());
+ 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(source);
+ }
+ else
+ {
+ printf(".");
+ }
+ printf(":");
+ if (symbol)
+ {
+ printf(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<ListASTNode*>(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);
+}
+