]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - tools/elftosb/elftosb2/ElftosbAST.cpp
Added source of Freescale's 'elftosb' tool
[karo-tx-uboot.git] / tools / elftosb / elftosb2 / ElftosbAST.cpp
diff --git a/tools/elftosb/elftosb2/ElftosbAST.cpp b/tools/elftosb/elftosb2/ElftosbAST.cpp
new file mode 100644 (file)
index 0000000..ab7732b
--- /dev/null
@@ -0,0 +1,1352 @@
+/*
+ * 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);
+}
+