1619 lines
42 KiB
C++
1619 lines
42 KiB
C++
/*
|
|
* 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()));
|
|
}
|
|
}
|
|
|
|
// open the file if it hasn't already been
|
|
if (!sourceFile->isOpen())
|
|
{
|
|
sourceFile->open();
|
|
}
|
|
|
|
// Make sure the source file supports symbols before going any further
|
|
if (!sourceFile->supportsNamedSymbols())
|
|
{
|
|
throw semantic_error(format_string("line %d: source file %s does not support symbols", getFirstLine(),
|
|
sourceFile->getPath().c_str()));
|
|
}
|
|
|
|
// Get the size of the symbol.
|
|
if (sourceFile->hasSymbol(*symbolName))
|
|
{
|
|
sizeInBytes = sourceFile->getSymbolSize(*symbolName);
|
|
}
|
|
}
|
|
else if (m_constantName)
|
|
{
|
|
// See if the "constant" is really a constant or if it's a source name.
|
|
if (manager->hasSourceFile(m_constantName))
|
|
{
|
|
sourceFile = manager->getSourceFile(m_constantName);
|
|
if (sourceFile)
|
|
{
|
|
sizeInBytes = sourceFile->getSize();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Regular constant.
|
|
if (!context.isVariableDefined(*m_constantName))
|
|
{
|
|
throw semantic_error(format_string("line %d: cannot get size of undefined constant %s", getFirstLine(),
|
|
m_constantName->c_str()));
|
|
}
|
|
|
|
int_size_t intSize = context.getVariableSize(*m_constantName);
|
|
switch (intSize)
|
|
{
|
|
case kWordSize:
|
|
sizeInBytes = sizeof(uint32_t);
|
|
break;
|
|
case kHalfWordSize:
|
|
sizeInBytes = sizeof(uint16_t);
|
|
break;
|
|
case kByteSize:
|
|
sizeInBytes = sizeof(uint8_t);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return function result as an expression node
|
|
return new IntConstExprASTNode(sizeInBytes);
|
|
}
|
|
|
|
#pragma mark = BinaryOpExprASTNode =
|
|
|
|
BinaryOpExprASTNode::BinaryOpExprASTNode(const BinaryOpExprASTNode &other)
|
|
: ExprASTNode(other)
|
|
, m_left()
|
|
, m_op(other.m_op)
|
|
, m_right()
|
|
{
|
|
m_left = dynamic_cast<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;
|
|
|
|
default:;
|
|
}
|
|
}
|
|
else if (m_op == kBooleanAnd)
|
|
{
|
|
// The left hand side is false, so the && operator's result must be false
|
|
// without regard to the right hand side.
|
|
result = 0;
|
|
}
|
|
else if (m_op == kBooleanOr)
|
|
{
|
|
// The left hand value is true so the || result is automatically true.
|
|
result = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Reduce right hand side always for most operators.
|
|
m_right = m_right->reduce(context);
|
|
rightIntConst = dynamic_cast<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;
|
|
default:;
|
|
}
|
|
}
|
|
|
|
// Create the result value.
|
|
int_size_t resultSize;
|
|
if (leftIntConst && rightIntConst)
|
|
{
|
|
resultSize = resultIntSize(leftIntConst->getSize(), rightIntConst->getSize());
|
|
}
|
|
else if (leftIntConst)
|
|
{
|
|
resultSize = leftIntConst->getSize();
|
|
}
|
|
else
|
|
{
|
|
// This shouldn't really be possible, but just in case.
|
|
resultSize = kWordSize;
|
|
}
|
|
return new IntConstExprASTNode(result, resultSize);
|
|
}
|
|
|
|
#pragma mark = IntSizeExprASTNode =
|
|
|
|
IntSizeExprASTNode::IntSizeExprASTNode(const IntSizeExprASTNode &other)
|
|
: ExprASTNode(other)
|
|
, m_expr()
|
|
, m_size(other.m_size)
|
|
{
|
|
m_expr = dynamic_cast<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 = KeyblobEntryASTNode =
|
|
|
|
KeyblobEntryASTNode::KeyblobEntryASTNode(const KeyblobEntryASTNode &other)
|
|
: ConstASTNode(other)
|
|
, m_fields()
|
|
{
|
|
m_fields = dynamic_cast<ListASTNode *>(other.m_fields->clone());
|
|
}
|
|
|
|
void KeyblobEntryASTNode::printTree(int indent) const
|
|
{
|
|
ConstASTNode::printTree(indent);
|
|
|
|
printIndent(indent + 1);
|
|
printf("fields:\n");
|
|
if (m_fields)
|
|
m_fields->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = IfStatementASTNode =
|
|
|
|
//! \warning Be careful; this method could enter an infinite loop if m_nextIf feeds
|
|
//! back onto itself. m_nextIf must be NULL at some point down the next if list.
|
|
IfStatementASTNode::IfStatementASTNode(const IfStatementASTNode &other)
|
|
: StatementASTNode()
|
|
, m_conditionExpr()
|
|
, m_ifStatements()
|
|
, m_nextIf()
|
|
, m_elseStatements()
|
|
{
|
|
m_conditionExpr = dynamic_cast<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 = EraseStatementASTNode =
|
|
|
|
EraseStatementASTNode::EraseStatementASTNode(const EraseStatementASTNode &other)
|
|
: StatementASTNode(other)
|
|
, m_doEraseAll(other.m_doEraseAll)
|
|
, m_doEraseAllUnsecure(other.m_doEraseAllUnsecure)
|
|
, m_memOption()
|
|
, m_rangeExpr()
|
|
{
|
|
m_rangeExpr = dynamic_cast<ExprASTNode *>(other.m_rangeExpr->clone());
|
|
m_memOption = dynamic_cast<ExprASTNode *>(other.m_memOption->clone());
|
|
}
|
|
|
|
void EraseStatementASTNode::printTree(int indent) const
|
|
{
|
|
printIndent(indent);
|
|
printf("%s%s%s\n", nodeName().c_str(), (m_doEraseAll ? "/ALL" : ""), (m_doEraseAllUnsecure ? "/UNSEC" : ""));
|
|
|
|
printIndent(indent + 1);
|
|
printf("range:\n");
|
|
if (m_rangeExpr)
|
|
m_rangeExpr->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("mem option:\n");
|
|
if (m_memOption)
|
|
m_memOption->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = MessageStatementASTNode =
|
|
|
|
MessageStatementASTNode::MessageStatementASTNode(const MessageStatementASTNode &other)
|
|
: StatementASTNode(other)
|
|
, m_type(other.m_type)
|
|
, m_message()
|
|
{
|
|
m_message = new std::string(*other.m_message);
|
|
}
|
|
|
|
void MessageStatementASTNode::printTree(int indent) const
|
|
{
|
|
StatementASTNode::printTree(indent);
|
|
printIndent(indent + 1);
|
|
printf("%s: %s\n", getTypeName(), m_message->c_str());
|
|
}
|
|
|
|
const char *MessageStatementASTNode::getTypeName() const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case kInfo:
|
|
return "info";
|
|
|
|
case kWarning:
|
|
return "warning";
|
|
|
|
case kError:
|
|
return "error";
|
|
}
|
|
|
|
return "unknown";
|
|
}
|
|
|
|
#pragma mark = LoadStatementASTNode =
|
|
|
|
LoadStatementASTNode::LoadStatementASTNode(const LoadStatementASTNode &other)
|
|
: StatementASTNode(other)
|
|
, m_data()
|
|
, m_target()
|
|
, m_loadOption()
|
|
{
|
|
m_data = other.m_data->clone();
|
|
m_target = other.m_target->clone();
|
|
m_loadOption = dynamic_cast<ExprASTNode *>(other.m_loadOption->clone());
|
|
}
|
|
|
|
void LoadStatementASTNode::printTree(int indent) const
|
|
{
|
|
StatementASTNode::printTree(indent);
|
|
|
|
printIndent(indent + 1);
|
|
printf("data:\n");
|
|
if (m_data)
|
|
m_data->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("target:\n");
|
|
if (m_target)
|
|
m_target->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("load option:\n");
|
|
if (m_loadOption)
|
|
m_loadOption->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = CallStatementASTNode =
|
|
|
|
CallStatementASTNode::CallStatementASTNode(const CallStatementASTNode &other)
|
|
: StatementASTNode(other)
|
|
, m_type(other.m_type)
|
|
, m_target()
|
|
, m_arg()
|
|
{
|
|
m_target = other.m_target->clone();
|
|
m_arg = other.m_arg->clone();
|
|
m_stackPointer = other.m_stackPointer->clone();
|
|
}
|
|
|
|
void CallStatementASTNode::printTree(int indent) const
|
|
{
|
|
printIndent(indent);
|
|
printf("%s%s%s\n", nodeName().c_str(), (m_type == kCallType ? "call" : "jump"), (m_isHAB ? "/HAB" : ""));
|
|
|
|
printIndent(indent + 1);
|
|
printf("target:\n");
|
|
if (m_target)
|
|
m_target->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("arg:\n");
|
|
if (m_arg)
|
|
m_arg->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("sp:\n");
|
|
if (m_stackPointer)
|
|
m_stackPointer->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = ResetStatementASTNode =
|
|
|
|
void ResetStatementASTNode::printTree(int indent) const
|
|
{
|
|
StatementASTNode::printTree(indent);
|
|
}
|
|
|
|
#pragma mark = MemEnableStatementASTNode =
|
|
|
|
MemEnableStatementASTNode::MemEnableStatementASTNode(const MemEnableStatementASTNode &other)
|
|
: StatementASTNode(other)
|
|
, m_memOption()
|
|
, m_rangeExpr()
|
|
{
|
|
m_rangeExpr = dynamic_cast<ExprASTNode *>(other.m_rangeExpr->clone());
|
|
m_memOption = dynamic_cast<ExprASTNode *>(other.m_memOption->clone());
|
|
}
|
|
|
|
void MemEnableStatementASTNode::printTree(int indent) const
|
|
{
|
|
StatementASTNode::printTree(indent);
|
|
|
|
printIndent(indent + 1);
|
|
printf("range:\n");
|
|
if (m_rangeExpr)
|
|
m_rangeExpr->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("mem option:\n");
|
|
if (m_memOption)
|
|
m_memOption->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = SourceASTNode =
|
|
|
|
SourceASTNode::SourceASTNode(const SourceASTNode &other)
|
|
: ASTNode(other)
|
|
, m_name()
|
|
{
|
|
m_name = new std::string(*other.m_name);
|
|
}
|
|
|
|
void SourceASTNode::printTree(int indent) const
|
|
{
|
|
printIndent(indent);
|
|
printf("%s(%s)\n", nodeName().c_str(), m_name->c_str());
|
|
}
|
|
|
|
#pragma mark = SectionMatchListASTNode =
|
|
|
|
SectionMatchListASTNode::SectionMatchListASTNode(const SectionMatchListASTNode &other)
|
|
: ASTNode(other)
|
|
, m_sections()
|
|
, m_source()
|
|
{
|
|
if (other.m_sections)
|
|
{
|
|
m_sections = dynamic_cast<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: ");
|
|
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<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);
|
|
}
|
|
|
|
#pragma mark = EncryptStatementASTNode =
|
|
|
|
EncryptStatementASTNode::EncryptStatementASTNode()
|
|
: StatementASTNode()
|
|
, m_statements()
|
|
, m_keyblobNumberExpr()
|
|
{
|
|
}
|
|
|
|
EncryptStatementASTNode::EncryptStatementASTNode(const EncryptStatementASTNode &other)
|
|
: StatementASTNode()
|
|
, m_statements()
|
|
, m_keyblobNumberExpr()
|
|
{
|
|
m_statements = dynamic_cast<ListASTNode *>(other.m_statements->clone());
|
|
m_keyblobNumberExpr = dynamic_cast<ExprASTNode *>(other.m_keyblobNumberExpr->clone());
|
|
}
|
|
|
|
void EncryptStatementASTNode::printTree(int indent) const
|
|
{
|
|
ASTNode::printTree(indent);
|
|
|
|
printIndent(indent + 1);
|
|
printf("Key blob Num:\n");
|
|
if (m_keyblobNumberExpr)
|
|
m_keyblobNumberExpr->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("statements:\n");
|
|
if (m_statements)
|
|
m_statements->printTree(indent + 2);
|
|
}
|
|
|
|
#pragma mark = KeywrapStatementASTNode =
|
|
|
|
KeywrapStatementASTNode::KeywrapStatementASTNode()
|
|
: StatementASTNode()
|
|
, m_statements()
|
|
, m_keyblobNumberExpr()
|
|
{
|
|
}
|
|
|
|
KeywrapStatementASTNode::KeywrapStatementASTNode(const KeywrapStatementASTNode &other)
|
|
: StatementASTNode()
|
|
, m_statements()
|
|
, m_keyblobNumberExpr()
|
|
{
|
|
m_statements = dynamic_cast<ListASTNode *>(other.m_statements->clone());
|
|
m_keyblobNumberExpr = dynamic_cast<ExprASTNode *>(other.m_keyblobNumberExpr->clone());
|
|
}
|
|
|
|
void KeywrapStatementASTNode::printTree(int indent) const
|
|
{
|
|
ASTNode::printTree(indent);
|
|
|
|
printIndent(indent + 1);
|
|
printf("Key blob Num:\n");
|
|
if (m_keyblobNumberExpr)
|
|
m_keyblobNumberExpr->printTree(indent + 2);
|
|
|
|
printIndent(indent + 1);
|
|
printf("statements:\n");
|
|
if (m_statements)
|
|
m_statements->printTree(indent + 2);
|
|
}
|