Extend responsibilities of FunctionViewWidget

Reduced IDcc interface functionality.

Fix a few bugs/warnings discovered by coverity.

Emit functionUpdate signal from project when function object internal
fields change.
This commit is contained in:
nemerle 2016-05-06 14:40:33 +02:00
parent 292e4041e1
commit 152625d67d
19 changed files with 303 additions and 203 deletions

View File

@ -626,7 +626,7 @@ public:
/* the instruction proper */
enum x86_insn_prefix prefix; /* prefixes ORed together */
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
char mnemonic[MAX_MNEM_STR];
char mnemonic[MAX_MNEM_STR+1];
x86_oplist_t *operands; /* list of explicit/implicit operands */
size_t operand_count; /* total number of operands */
size_t explicit_count; /* number of explicit operands */

View File

@ -10,12 +10,7 @@ class IStructuredTextTarget;
struct IDcc {
static IDcc *get();
virtual void BaseInit()=0;
virtual void Init(QObject *tgt)=0;
virtual void analysis_Once()=0;
virtual bool load(QString name)=0; // load and preprocess -> find entry point
virtual void prtout_asm(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
virtual void prtout_cpp(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
virtual size_t getFuncCount()=0;
virtual const lFunction &validFunctions() const =0;
virtual QDir installDir()=0;
virtual QDir dataDir(QString kind)=0;

View File

@ -175,7 +175,7 @@ struct AssignType : public HlTypeSupport
protected:
public:
Expr *m_lhs;
Expr *rhs;
Expr *m_rhs;
AssignType() {}
Expr *lhs() const {return m_lhs;}
void lhs(Expr *l);
@ -262,7 +262,7 @@ struct LLOperand
bool is_offset; // set by jumps
bool is_compound;
size_t width;
//union {/* Source operand if (flg & I) */
/* Source operand if (flg & I) */
struct { /* Call & # actual arg bytes */
Function *proc; /* pointer to target proc (for CALL(F))*/
int cb; /* # actual arg bytes */
@ -339,20 +339,12 @@ public:
}
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
void setFlags(uint32_t flag) {flg |= flag;}
void clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
void clrFlags(uint32_t flag);
uint32_t getFlag() const {return flg;}
uint32_t GetLlLabel() const { return label;}
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
bool match(llIcode op)
{
return (getOpcode()==op);
@ -363,19 +355,19 @@ public:
}
bool match(llIcode op,eReg dest)
{
return (getOpcode()==op)&&m_dst.regi==dest;
return (getOpcode()==op) and match(dest);
}
bool match(llIcode op,eReg dest,uint32_t flgs)
{
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
return match(op) and match(dest) and testFlags(flgs);
}
bool match(llIcode op,eReg dest,eReg src_reg)
{
return (getOpcode()==op) and (m_dst.regi==dest) and (m_src.regi==src_reg);
return match(op) and match(dest) and (m_src.regi==src_reg);
}
bool match(eReg dest,eReg src_reg)
{
return (m_dst.regi==dest) and (m_src.regi==src_reg);
return match(dest) and (m_src.regi==src_reg);
}
bool match(eReg dest)
{
@ -383,7 +375,7 @@ public:
}
bool match(llIcode op,uint32_t flgs)
{
return (getOpcode()==op) and testFlags(flgs);
return match(op) and testFlags(flgs);
}
void set(llIcode op,uint32_t flags)
{
@ -416,32 +408,17 @@ public:
{
setOpcode(0);
}
const LLOperand &src() const {return m_src;}
LLOperand &src() {return m_src;}
void replaceSrc(const LLOperand &with)
{
m_src = with;
}
void replaceSrc(eReg r)
{
m_src = LLOperand::CreateReg2(r);
}
void replaceSrc(int64_t r)
{
m_src = LLOperand::CreateImm2(r);
}
void replaceDst(const LLOperand &with)
{
m_dst = with;
}
// void replaceDst(eReg r)
// {
// dst = LLOperand::CreateReg2(r);
// }
ICODE *m_link;
const LLOperand & src() const { return m_src; }
LLOperand & src() { return m_src; }
void replaceSrc(const LLOperand &with) { m_src = with; }
void replaceSrc(eReg r) { m_src = LLOperand::CreateReg2(r); }
void replaceSrc(int64_t r) { m_src = LLOperand::CreateImm2(r); }
void replaceDst(const LLOperand &with) { m_dst = with; }
condId idType(opLoc sd) const;
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
ICODE * m_link;
};
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */

View File

@ -158,6 +158,7 @@ public slots:
void onCommandStreamFinished(bool state);
signals:
void newFunctionCreated(PtrFunction);
void functionUpdate(const PtrFunction &);
void loaderSelected();
void commandListChanged();
protected:

View File

@ -578,7 +578,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
return;
/* Insert on rhs of ticode, if possible */
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.m_rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
if (res)
{
picode->invalidate();
@ -617,7 +617,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
return;
/* Insert on rhs of ticode, if possible */
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.rhs, longIdx);
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.m_rhs, longIdx);
if (res)
{
picode->invalidate();
@ -758,11 +758,11 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
if(isLong)
{
forwardSubsLong (lhs_ident->ident.idNode.longIdx,
p_hl.asgn.rhs, picode,ticode,
p_hl.asgn.m_rhs, picode,ticode,
&numHlIcodes);
}
else
this->forwardSubs (lhs_ident, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
this->forwardSubs (lhs_ident, p_hl.asgn.m_rhs, picode, ticode, numHlIcodes);
break;
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
@ -770,7 +770,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
{
assert(lhs_ident);
res = Expr::insertSubTreeLongReg (
p_hl.asgn.rhs,
p_hl.asgn.m_rhs,
t_hl.exp.v,
lhs_ident->ident.idNode.longIdx);
}
@ -780,7 +780,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
assert(lhs_reg);
res = Expr::insertSubTreeReg (
t_hl.exp.v,
p_hl.asgn.rhs,
p_hl.asgn.m_rhs,
id_arr[lhs_reg->regiIdx].id.regi,
this);
}
@ -914,7 +914,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
(ticode->hl()->opcode != HLI_RET)))
continue;
if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
if (_icHl.asgn.m_rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
end(), locals))
{
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
@ -973,9 +973,9 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
switch (ti_hl->opcode)
{
case HLI_ASSIGN:
assert(ti_hl->asgn.rhs);
assert(ti_hl->asgn.m_rhs);
_exp = _icHl.call.toAst();
res = Expr::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals);
res = Expr::insertSubTreeReg (ti_hl->asgn.m_rhs,_exp, _retVal->id.regi, &locals);
if (not res)
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
//TODO: HERE missing: 2 regs
@ -1023,8 +1023,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
switch (_icHl.opcode)
{
case HLI_ASSIGN:
/* Replace rhs of current icode into target
* icode expression */
/* Replace rhs of current icode into target icode expression */
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{
ticode = picode->du1.idx[0].uses.front();
@ -1048,10 +1047,11 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
_exp = g_exp_stk.pop(); /* pop last exp pushed */
switch (ticode->hl()->opcode) {
case HLI_ASSIGN:
forwardSubsLong (dynamic_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
forwardSubsLong (static_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
_exp, picode.base(), ticode, &numHlIcodes);
break;
case HLI_JCOND: case HLI_PUSH:
case HLI_JCOND:
case HLI_PUSH:
res = Expr::insertSubTreeLongReg (_exp,
ticode->hlU()->exp.v,
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
@ -1079,7 +1079,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
AstIdent::Long(&locals, DST,
ticode,HIGH_FIRST, picode.base(),
eDEF, *(++iICODE(ticode))->ll()));
ticode->hlU()->asgn.rhs = _exp;
ticode->hlU()->asgn.m_rhs = _exp;
picode->invalidate();
numHlIcodes--;
break;

View File

@ -5,53 +5,12 @@ struct DccImpl : public IDcc {
PtrFunction m_current_func;
// IDcc interface
public:
void BaseInit()
{
m_current_func = nullptr;
}
void Init(QObject *tgt)
{
}
PtrFunction GetCurFuncHandle() {
return m_current_func;
}
void analysis_Once()
{
if(m_current_func==nullptr)
return;
if(m_current_func->nStep==0) { // unscanned function
}
}
bool load(QString name)
{
option.filename = name;
Project::get()->create(name);
return Project::get()->addLoadCommands(name);
}
void prtout_asm(PtrFunction f,IStructuredTextTarget *tgt, int level) override
{
// if (m_current_func->nStep == 0)
// return;
// XmlOutPro out(iOut);
// FuncLL the(m_Cur_Func->ll.m_asmlist);
// the.prtout_asm(m_Cur_Func, &m_Cur_Func->m_varll, &out);
f->toStructuredText(tgt,level);
}
void prtout_cpp(PtrFunction f,IStructuredTextTarget *, int level) override
{
}
bool isValidFuncHandle(ilFunction f) {
return f != Project::get()->functions().end();
}
size_t getFuncCount()
{
return Project::get()->functions().size();
}
const lFunction &validFunctions() const
{
return Project::get()->functions();
}
void SetCurFunc_by_Name(QString v)
{
PtrFunction p(Project::get()->findByName(v));

View File

@ -828,7 +828,7 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
const LLInst &inst(*insn);
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
out->addSpace(4);
out->addTaggedString(XT_Number,strHex(insn->label));
out->addTaggedString(XT_Number,QString("%1").arg(insn->label,8,16,QChar('0').toUpper()));
out->addSpace(4);
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
out->addSpace(2);
@ -905,17 +905,12 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
}
else if (inst.testFlags(I) )
{
out->addTaggedString(XT_AsmLabel,strHex(inst.src().getImm2()));
// j = inst.src().getImm2();
// if (pl.count(j)==0) /* Forward jump */
// {
// pl[j] = ++g_lab;
// }
// if (inst.getOpcode() == iJMPF)
// {
// operands_s<<" far ptr ";
// }
// operands_s<<"L"<<pl[j];
int64_t tgt_addr = inst.src().getImm2();
if (inst.getOpcode() == iJMPF)
{
out->addTaggedString(XT_Keyword," far ptr ");
}
out->addTaggedString(XT_AsmLabel,QString("L_%1").arg(strHex(tgt_addr)));
}
else if (inst.getOpcode() == iJMPF)
{
@ -928,6 +923,36 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
}
break;
case iCALL: case iCALLF:
if (inst.testFlags(I))
{
out->addTaggedString(XT_Keyword,QString("%1 ptr ").arg((inst.getOpcode() == iCALL) ? "near" : "far"));
out->addTaggedString(XT_AsmLabel,(inst.src().proc.proc)->name);
}
else if (inst.getOpcode() == iCALLF)
{
out->addTaggedString(XT_Keyword,"dword ptr ");
strSrc(out,insn,true);
}
else
strDst(out,I,inst.src());
break;
case iENTER:
out->addTaggedString(XT_AsmOffset,strHex(inst.m_dst.off));
out->prtt(", ");
out->addTaggedString(XT_AsmOffset,strHex(inst.src().getImm2()));
break;
case iRET:
case iRETF:
case iINT:
if (inst.testFlags(I))
{
out->addTaggedString(XT_Number,strHex(inst.src().getImm2()));
}
break;
}
out->addEOL();
}

View File

@ -399,7 +399,8 @@ void Function::highLevelGen()
}
break;
case iMOV: pIcode->setAsgn(lhs, rhs);
case iMOV:
pIcode->setAsgn(lhs, rhs);
break;
case iMUL:
@ -432,7 +433,8 @@ void Function::highLevelGen()
break;
case iRET:
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
case iRETF:
pIcode->setUnary(HLI_RET, nullptr);
break;
case iSHL:
@ -461,6 +463,8 @@ void Function::highLevelGen()
rhs = new BinaryOperator(XOR,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
//TODO: default: // mostly to silence static analyzer warnings ?
// delete rhs;
}
}
@ -532,7 +536,7 @@ QString AssignType::writeOut(Function *pProc, int *numLoc) const
{
return QString("%1 = %2;\n")
.arg(m_lhs->walkCondExpr (pProc, numLoc))
.arg(rhs->walkCondExpr (pProc, numLoc));
.arg(m_rhs->walkCondExpr (pProc, numLoc));
}
QString CallType::writeOut(Function *pProc, int *numLoc) const
{
@ -553,7 +557,7 @@ void HLTYPE::set(Expr *l, Expr *r)
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
assert(dynamic_cast<UnaryOperator *>(l));
asgn.m_lhs=l;
asgn.rhs=r;
asgn.m_rhs=r;
}
/* Returns a string with the contents of the current high-level icode.
* Note: this routine does not output the contens of HLI_JCOND icodes. This is

View File

@ -67,6 +67,15 @@ extern bundle cCode;
* is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be backpatched
* onto code in cCode.code */
void LLInst::clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
void LLInst::emitGotoLabel (int indLevel)
{
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */

View File

@ -198,7 +198,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
pstate->JCond.immed++;
if (ll->getOpcode() == iJAE or ll->getOpcode() == iJA)
pstate->JCond.regi = prev.ll()->m_dst.regi;
fBranch = (bool) (ll->getOpcode() == iJB or ll->getOpcode() == iJBE);
fBranch = (ll->getOpcode() == iJB or ll->getOpcode() == iJBE);
}
StCopy = *pstate;
@ -212,8 +212,10 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
/* Next icode. Note: not the same as GetLastIcode() because of the call
to FollowCtrl() */
pIcode = Icode.GetIcode(ip);
} /* Fall through to do the jump path */
/* do the jump path */
done = process_JMP (*pIcode, pstate, pcallGraph);
break;
}
/*** Jumps ***/
case iJMP:
case iJMPF: /* Returns true if we've run into a loop */
@ -232,7 +234,9 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
case iRET:
case iRETF:
this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR;
/* Fall through */
this->flg &= ~TERMINATES;
done = true;
break;
case iIRET:
this->flg &= ~TERMINATES;
done = true;
@ -868,7 +872,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]);
if(psym->size>1)
{
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]>>8);
pstate->setMemoryByte(psym->label,uint8_t(pstate->r[srcReg]>>8));
//prog.image()[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8);
}
psym->duVal.setFlags(eDuVal::DEF);
@ -1276,7 +1280,9 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
use(SRC, pIcode, this, pstate, cb);
break;
case iLOOP: case iLOOPE: case iLOOPNE:
case iLOOP:
case iLOOPE:
case iLOOPNE:
pIcode.du.def.addReg(rCX);
pIcode.du1.addDef(rCX);
case iJCXZ:
@ -1331,7 +1337,8 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
pIcode.du.use.addReg(rDX).addReg(sseg);
break;
case iIN: case iOUT:
case iIN:
case iOUT:
def(DST, pIcode, this, pstate, cb);
if (not Imm)
{

View File

@ -187,7 +187,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
/* Do ps (actual arguments) */
STKSYM newsym;
newsym.setArgName(call_args_stackframe->size());
newsym.actual = picode->hl()->asgn.rhs;
newsym.actual = picode->hl()->asgn.m_rhs;
newsym.regs = lhs;
/* Mask off high and low register(s) in picode */
switch (type) {

View File

@ -228,6 +228,7 @@ void Project::processFunctionCommands(const PtrFunction &func,int count) {
}
}
emit commandListChanged();
emit functionUpdate(func);
}
void Project::resetCommandsAndErrorState()
{

View File

@ -630,7 +630,7 @@ static int signex(uint8_t b)
static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off)
{
/* If not to register (i.e. to r/m), and talking about r/m, then this is dest */
LLOperand *pm = (! (stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src();
LLOperand *pm = (! bool(stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src();
/* Set segment. A later procedure (lookupAddr in proclist.c) will
* provide the value of this segment in the field segValue.

View File

@ -12,7 +12,7 @@
#include <QtWidgets>
#include <QLabel>
#include <QFileDialog>
IDcc* g_EXE2C = NULL;
IDcc* g_IDCC = NULL;
extern bool exe2c_Init();
DccMainWindow::DccMainWindow(QWidget *parent) :
@ -22,9 +22,9 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
ui->setupUi(this);
ui->statusbar->addPermanentWidget(new QLabel("Test"));
g_EXE2C = IDcc::get();
g_EXE2C->BaseInit();
g_EXE2C->Init(this);
g_IDCC = IDcc::get();
g_IDCC->BaseInit();
g_IDCC->Init(this);
m_last_display = nullptr;
m_command_queue = new CommandQueueView(this);
@ -36,20 +36,12 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
// we are beeing signalled when display is requested
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
connect(Project::get(),SIGNAL(newFunctionCreated(PtrFunction)),SLOT(onNewFunction(PtrFunction)));
connect(Project::get(),SIGNAL(functionUpdate(const PtrFunction &)),SLOT(onFunctionUpdated(const PtrFunction &)));
this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget);
this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue);
connect(m_functionlist_widget,&FunctionListDockWidget::selectFunction,
m_command_queue, &CommandQueueView::onCurrentFunctionChanged);
m_asm_view = new FunctionViewWidget(this);
m_asm_view->setWindowTitle(tr("Assembly listing"));
ui->mdiArea->addSubWindow(m_asm_view);
//m_internal_view = new FunctionViewWidget;
//m_internal_view->setWindowTitle(QApplication::tr("Internal listing"));
//ui->mdiArea->addSubWindow(m_internal_view);
m_c_view = new FunctionViewWidget;
m_c_view->setWindowTitle(tr("Decompiled"));
ui->mdiArea->addSubWindow(m_c_view);
}
DccMainWindow::~DccMainWindow()
@ -71,13 +63,22 @@ void DccMainWindow::changeEvent(QEvent *e)
void DccMainWindow::onFunctionSelected(PtrFunction func) {
m_selected_func = func;
}
// TODO: consider increasing granularity of change events to reduce redraw/refresh spam
void DccMainWindow::onFunctionUpdated(const PtrFunction &f) {
// some function was updated refresh the list and the view if open
auto iter = m_map_function_to_view.find(f);
if(iter!=m_map_function_to_view.end()) {
iter->second->renderCurrent();
}
emit functionListChanged();
}
void DccMainWindow::onNewFunction(PtrFunction f) {
emit functionListChanged();
}
void DccMainWindow::onOptim()
{
Project::get()->processCommands();
g_EXE2C->analysis_Once();
g_IDCC->analysis_Once();
emit functionListChanged();
if(m_last_display==m_selected_func)
{
@ -87,7 +88,7 @@ void DccMainWindow::onOptim()
void DccMainWindow::onOptim10()
{
for(int i=0; i<10; i++)
g_EXE2C->analysis_Once();
g_IDCC->analysis_Once();
emit functionListChanged();
if(m_last_display==m_selected_func)
{
@ -101,20 +102,43 @@ void DccMainWindow::onOpenFile_Action()
tr("Select DOS executable"),
".",
tr("Executable files (*.exe *.EXE *.com *.COM)"));
if(!g_EXE2C->load(name)) {
if(!g_IDCC->load(name)) {
QMessageBox::critical(this,tr("Error"),QString(tr("Cannot open file %1")).arg(name));
}
//bool m_bSucc = m_xTextBuffer.LoadFromFile(lpszPathName);
emit functionListChanged();
}
void DccMainWindow::functionViewClosed() {
FunctionViewWidget *sndr = qobject_cast<FunctionViewWidget *>(sender());
for(auto iter = m_mdi_function_views.begin(); iter!=m_mdi_function_views.end(); ++iter) {
if(*iter==sndr) {
m_map_function_to_view.erase(sndr->viewedFunction());
m_mdi_function_views.erase(iter);
break;
}
}
ui->mdiArea->removeSubWindow(sndr);
sndr->deleteLater();
}
void DccMainWindow::displayCurrentFunction()
{
if(m_last_display!=m_selected_func)
if(m_last_display!=m_selected_func) {
m_last_display=m_selected_func;
g_EXE2C->prtout_asm(m_last_display, m_asm_view);
//g_EXE2C->prtout_itn(m_internal_view);
g_EXE2C->prtout_cpp(m_last_display,m_c_view);
// Check if function's view is already open, if it is, acivate it
auto iter = m_map_function_to_view.find(m_selected_func);
if(iter!=m_map_function_to_view.end()) {
ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(iter->second->parent()));
return;
}
FunctionViewWidget *view = new FunctionViewWidget(m_selected_func,this);
view->setWindowTitle(QString(tr("Listing for %1")).arg(m_selected_func->name));
connect(view,SIGNAL(close()),SLOT(functionViewClosed()));
ui->mdiArea->addSubWindow(view);
view->show();
m_mdi_function_views.push_back(view);
m_map_function_to_view[m_selected_func] = view;
}
}
void DccMainWindow::prt_log(const char *v)
{

View File

@ -8,6 +8,7 @@
#include <QAbstractTableModel>
#include <QVariant>
#include <vector>
#include <unordered_map>
class FunctionViewWidget;
class FunctionListDockWidget;
@ -36,11 +37,12 @@ private slots:
void on_actionExit_triggered();
void onNewFunction(PtrFunction f);
void onFunctionSelected(PtrFunction func);
void functionViewClosed();
void onFunctionUpdated(const PtrFunction & f);
private:
FunctionViewWidget *m_asm_view;
std::vector<FunctionViewWidget *> m_mdi_function_views;
std::unordered_map<PtrFunction,FunctionViewWidget *> m_map_function_to_view;
// FunctionViewWidget *m_internal_view;
FunctionViewWidget *m_c_view;
CommandQueueView *m_command_queue;
FunctionListDockWidget *m_functionlist_widget;
Ui::DccMainWindow *ui;

View File

@ -8,7 +8,7 @@
#include <QtCore>
//#include "exe2c.h"
extern IDcc *g_EXE2C;
extern IDcc *g_IDCC;
FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) :
QDockWidget(parent),
ui(new Ui::FunctionListDockWidget)

View File

@ -1,16 +1,21 @@
#include <QDebug>
#include <QtCore>
#include "FunctionViewWidget.h"
#include "ui_FunctionViewWidget.h"
#include "RenderTags.h"
#include "Procedure.h"
#include <QDebug>
#include <QtCore>
#include "dcc_interface.h"
extern IDcc* g_IDCC;
//#include "XMLTYPE.h"
FunctionViewWidget::FunctionViewWidget(QWidget *parent) :
FunctionViewWidget::FunctionViewWidget(PtrFunction func, QWidget *parent) :
QWidget(parent),
ui(new Ui::FunctionViewWidget)
ui(new Ui::FunctionViewWidget),
m_viewed_function(func)
{
ui->setupUi(this);
m_current_rendering = new QTextDocument(ui->textEdit);
m_doc_cursor = new QTextCursor(m_current_rendering);
m_assembly_rendering = new QTextDocument(ui->textEdit);
m_doc_cursor = new QTextCursor(m_assembly_rendering);
ui->textEdit->setTextBackgroundColor(Qt::black);
m_current_format = m_doc_cursor->blockFormat();
m_current_format.setNonBreakableLines(true); // each block is single line
@ -25,6 +30,11 @@ FunctionViewWidget::~FunctionViewWidget()
delete ui;
}
void FunctionViewWidget::renderCurrent()
{
m_viewed_function->toStructuredText(this,0);
}
void FunctionViewWidget::prtt(const char *s)
{
m_doc_cursor->insertText(s);
@ -50,7 +60,7 @@ void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
switch(tag_type)
{
case XT_Function:
m_current_rendering->clear();
m_assembly_rendering->clear();
m_chars_format.setForeground(Qt::white);
m_doc_cursor->setBlockFormat(m_current_format);
m_doc_cursor->setCharFormat(m_chars_format);
@ -79,9 +89,9 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
// TODO: What about attributes with spaces?
QFile res("result.html");
res.open(QFile::WriteOnly);
res.write(m_current_rendering->toHtml().toUtf8());
res.write(m_assembly_rendering->toHtml().toUtf8());
res.close();
ui->textEdit->setDocument(m_current_rendering);
ui->textEdit->setDocument(m_assembly_rendering);
collected_text.clear();
break;
}
@ -100,3 +110,7 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
qDebug()<<"Tag end:"<<tag_type;
}
}
void FunctionViewWidget::on_tabWidget_currentChanged(int index)
{
renderCurrent();
}

View File

@ -4,28 +4,42 @@
#include "StructuredTextTarget.h"
#include "RenderTags.h"
#include <memory>
#include <QWidget>
#include <QTextDocument>
#include <QTextBlockFormat>
//#include "XmlPrt.h"
class Function;
typedef std::shared_ptr<Function> PtrFunction;
namespace Ui {
class FunctionViewWidget;
}
//TODO: convert 'controllers' of each hex/asm/high-level areas into standalone classes
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
{
Q_OBJECT
QTextDocument *m_current_rendering;
PtrFunction m_viewed_function; // 'model' this view is bound to
QTextDocument *m_assembly_rendering;
QTextCursor* m_doc_cursor;
QTextBlockFormat m_current_format;
QTextCharFormat m_chars_format;
public:
explicit FunctionViewWidget(QWidget *parent = 0);
explicit FunctionViewWidget(PtrFunction func,QWidget *parent = 0);
~FunctionViewWidget();
const PtrFunction &viewedFunction() const { return m_viewed_function; }
void renderCurrent();
// IStructuredTextTarget interface
void prtt(const char * s);
void prtt(const QString &s);
void addEOL() override;
void TAGbegin(enum TAG_TYPE tag_type, void * p);
void TAGend(enum TAG_TYPE tag_type);
private slots:
void on_tabWidget_currentChanged(int index);
private:
Ui::FunctionViewWidget *ui;
QString collected_text;

View File

@ -6,14 +6,51 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>708</width>
<height>582</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="binaryTab">
<attribute name="title">
<string>Binary</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTextEdit" name="edtBinary">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Corbel'; font-size:10pt; font-weight:400; font-style:normal;&quot; bgcolor=&quot;#000000&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="assemblyTab">
<attribute name="title">
<string>Assembly</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTextEdit" name="textEdit">
<property name="undoRedoEnabled">
@ -36,6 +73,37 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
<widget class="QWidget" name="highLevelTab">
<attribute name="title">
<string>High level</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="edtHighLevel">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Corbel'; font-size:10pt; font-weight:400; font-style:normal;&quot; bgcolor=&quot;#000000&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>