📄 labelmaniger_c.cpp
字号:
//---------------------------------------------------------------------------
// LabelManiger_C.cpp
//---------------------------------------------------------------------------
#include "Tokens_H.h"
#include "MAsmber_H.h"
#include "LabelManiger_H.h"
#include "OBJModule_H.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#define IsSameSeg(a,b) (a).rseg == (b).rseg
#define IsSameTyp(a,b) (a).typ == (b).typ
#define ifRel(x,y) if(a.rel == x && b.rel == y)
#define ifTypNum(x,y) if(a.typ x LB_NUM && b.typ y LB_NUM)
//---------------------------------------------------------------------------
//------ 析构器 -------------------------------------------------------------
LabelManager::~LabelManager()
{ register JLabelNode* p;
for( ; head; )
{ p = head->next; delete head; head = p; } // end for
} // end destructor
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 规限标号名字的长度。(MaxNameLen)
//---------------------------------------------------------------------------
inline void LabelManager::TruncLBsName(Jstring& name)
{ if(name.getLen() > MaxNameLen)
{ masm.OutWarning(LBLTooLongWarn); name.Trunc(MaxNameLen); } // endif
// else do nothing
} // end TruncLBsName
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 预装SFR组。
//---------------------------------------------------------------------------
void LabelManager::LoadSFR51(SpecialRegs* init)
{ for( register SpecialRegs* ut = init; ut->vtyp; ++ut )
{ LabelPreAdd(ut->name, ut->vtyp, ut->addr); } // end for
} // end LoadSFR51
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 往链表中添加一个LabelNode结点。
//---------------------------------------------------------------------------
void LabelManager::AddLabelNode(JLabelNode* t)
{ t->next = head->next; head->next = t; // 从表头插入
if(++LBL_NUM > Max_LBL_Sum)
{ FatalErr("\nToo many labels!"); } // endif
} // end AddNode
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// true = found(p!=NULL), false = not found(p==NULL)
//---------------------------------------------------------------------------
bool LabelManager::SearchLinkList(const Jstring& str, JLabelNode* &p)
{ for( p = head->next;
p && (p->LName != str);
p = p->next ); // end for
return (bool)p;
} // SearchLinkList
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 返回p 存放所找到的标号结点. true = found, false = not found
// Notice, p has been modified !! But, str NOT been modified, Read only.
// beginning == NULL, 从头开始搜。否则,从beginning->next开始搜。
// 搜完,如果beginning != NULL, 则从头开始搜,搜到beginning为止。
// 该函数还负责给标号节点的evenUse域赋值。
// -----------------------------------------
// 注意,beginning所指向的节点没有搜!!
//---------------------------------------------------------------------------
bool LabelManager::
SearchLabel(const Jstring& str, JLabelNode* &p, JLabelNode *const beginning)
{ if(beginning != NULL) { p = beginning; } // endif
else { p = head; } // end else
// 从参考点的next开始搜索。逐个对比标号的名称。
for( p = p->next; p &&(p->LName != str); p = p->next ); // end for
// 找到就返回true。
if(p) { p->evenUse = true; return true; } // endif
// 但是如果找不到,而开始又已经是从头开始搜的话,则返回false。
if(beginning == NULL) { return false; } // endif
// 若原来不是从头开始的,就从头开始重新搜,直到搜到或到达参考点。
for( p = head->next; p != beginning; p = p->next )
{ if(p->LName == str)
{ p->evenUse = true; return(!p->IsVariable()); } // endif
} // end for
return false;
} // end SearchLabel
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 根据给出的标号名,找到该标号, 如果ValOK,返回该标号,否则返回NULL。
// 如果发生各种各样的错误,则带回相应的错误码。
// 它是SearchLabel()的增强版。
// 该程序会对标号的Value和ValOK进行操控。
// ( 所有标号都应该通过AddLabel()建立好。)(外部变量的Value==0; ValueOK!)
// err = LabNotExist 10 (Pass x)
// err = LabNotReady 11
// err = LabValNotOk 12 (??? printf)
//---------------------------------------------------------------------------
JLabelNode* LabelManager::
SearchLabelCal(const Jstring& name, ERR &err, JLabelNode *const ReLb)
{ err = OK_no_Err; // 对err清零
register JLabelNode* lab; // 标号句柄承载。
if( SearchLabel(name, lab, ReLb) ) // Found an existing label. lab带值返回。
{ if( lab->IsValOK() ) { return lab; } // 直接拿出结果。 数值正确得到。
// 数值未得到.(ValOk == false)
if(lab->vv.Indirect) // 若标号属性是间接寻址,即CODE标号。
{ lab->Value = lab->LnPt->lc; // 捉摸值, 这时标号还没OK。
if(lab->LnPt->LineIsOK()) { lab->vv.ValOk = true; } // endif
else { err = LabNotReady; } // end else
return lab;
} // endif (lab->Indirect)
else // (lab->Indirect==false) // 标号属性不是间接寻址,即常量或变量。
{ err = CalLabValChk(*lab); return lab; } // end else
} // endif SearchLabel
else // Label Not Found!
{ err = LabNotExist;
if(!masm.Pass) { masm.OutputErr(LabelUnDefErr); } // endif
return NULL;
} // end else
} // end SearchLabelCal
//---------------------------------------------------------------------------
#define Constant false
//---------------------------------------------------------------------------
// err = BitAddrOutRange (x)
// err = DATAAddrOutRange (x)
// err = LocAddrOutRange (x)
// err = LabelNameDulplicated (x)
// ----- 来自OPAct's err: -------
// err = BadRelExp (x)
// err = IllExpTypOp (x)
// err = DividedByZero (x)
// err = BitAddrOutRange (x)
// err = ShiftsOverflow (x)
// ----- 来自OPNDAct's err: -----
// err = LabNotExist 10 (Pass x)
// err = LabNotReady 11
// err = LabValNotOk 12 (??? printf)
// --------------------------------------------------------------------------
// 往表中添加标号结点,标号名为Name, 并返回指针。如果有err,添加失败。
//---------------------------------------------------------------------------
// labelTp, 是强制转换的类型。
// rSeg, 是强制的参考段。
// 如果pt==NULL, 则不计算Value值。否则根据pt所指的表达式计算Value值。
// 如果var==true, 则添加的标号为变量。否则为常量。
// Crln是创建该标号的行号。Ind==true是间接寻址,Ext==true是外部变量。
// rSeg==NULL 或指向绝对段时,atrb='A'。
// rSeg 指向可定位段时,atrb='R'。 (atrb的取值是由rSeg的取值决定的。)
//---------------------------------------------------------------------------
JLabelNode* LabelManager::
AddLabel( ERR &err, // 带值返回的错误号
Jstring &name, // 标号名称
int8u labelTp, // 标号类型
bool var, // 是否变量
AsmLine* Crln, // 创建该标号的汇编行
Tokenfield* pt, // 数值表达式指针
ASM_Segment* rSeg, // 该标号的参考段 (NULL)
bool Ind, // 是否间接 (false)
bool Ext ) // 是否外部 (false)
#define CAL_LABEL(b) clearNest(); err = CalLabValChk(b);
//-----------------------------------------------------------
{ TruncLBsName(name); // 规限标号名称长度。
err = OK_no_Err; // 对err清零。
JLabelNode* temp; // 标号句柄承载。
if( SearchLinkList(name, temp) ) // 从链头搜索,temp带回搜索值。
{ if(temp->IsVariable()) // 如果它是已登记的变量,重新更新该节点。
{ int8u atrb = 'A'; // 若rSeg==NULL, 则atrb一定是'A'。
if(rSeg) { atrb = rSeg->GetRelType(); } // endif
temp = new JLabelNode(name, pt, labelTp, atrb, var, Crln, rSeg); // 创建新结点
AddLabelNode(temp); // 原变量节点并没有销毁。
CAL_LABEL(*temp); // 先添加,后计算。
// 带回err值。如果成功,设置好了Value值,Attrb值等。不一定成功。
} // endif
else // 它不是变量。它是常量。
{ if(masm.Pass) // Pass1
{ err = LabelNameDulplicated; masm.OutputErr(LblNameDuplcateErr); } // endif
else // Pass2 它是已登记的常量,但Pass1计算不成功
{ CAL_LABEL(*temp); } // end else 计算常量
// 带回err值。在Pass2中还计算不成功的话,源汇编程序报错。
} // end else
return temp;
} // endif Search
// Not found(temp==NULL), create a new one
if(Ext) // 如果是外部变量,直接添加。
{ temp = new JLabelNode(name, pt, labelTp, 'E', Constant, Crln); // 创建新结点
AddLabelNode(temp); return temp;
} // endif
// Now, the label is not external.
int8u atrb = 'A';
if(rSeg) { atrb = rSeg->GetRelType(); } // endif
temp = new JLabelNode(name, pt, labelTp, atrb, var, Crln, rSeg, Ind); // 创建新结点
AddLabelNode(temp);
// 标号和段名不计算! (pt==NULL, 表达式指针为空。)
if(pt && !Ind) { CAL_LABEL(*temp); } // endif 悄悄计算...得到err。
return temp; // 第一次只登记,不计算。Yeah...
} // end AddLabel
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 对Lab进行处理。
// 根据pt指向的表达式,给Lab标号的Value赋值,并作检查。
//---------------------------------------------------------------------------
// err = BitAddrOutRange (x)
// err = DATAAddrOutRange (x)
// err = LocAddrOutRange (x)
// err = REGOutRange (x)
// ----- 来自OPAct's err: -----
// err = BadRelExp (x)
// err = IllExpTypOp (x)
// err = DividedByZero (x)
// err = BitAddrOutRange (x)
// err = ShiftsOverflow (x)
// ----- 来自OPNDAct's err: -----
// err = LabNotExist 10 (Pass x)
// err = LabNotReady 11
// err = LabValNotOk 12 (??? printf)
//---------------------------------------------------------------------------
// labelTp, 是强制转换的类型。 ( labelTp==LB_NUM, 表示不强制。)
// rSeg, 是强制的参考段。 ( rSeg==NULL, 表示不强制。)
//---------------------------------------------------------------------------
ERR LabelManager::CalLabValChk(JLabelNode &Lab)
{ if(Lab.ExpPt == NULL) { return OK_no_Err; } // endif
ERR err;
const TriVal* result = CalExpr(err, Lab.ExpPt, &Lab, false);
// err带回返回值。result指向结果。
if(err) { return err; } // 计算过程中发生错误.
// Now, no error.
// 根据result(TriVal结构)设置label。
if( Lab.vv.LBLTyp != LB_NUM && result->typ != LB_NUM // 如果类型不匹配,将发出警告。
&& Lab.vv.LBLTyp != result->typ ) // 若强制转换为NUM,则不发出警告。
{ masm.OutWarning(LBLTypNotMatchWarn); } // endif
// 强制转换类型 (只能由LB_NUM类型转换成其他类型)
if(Lab.vv.LBLTyp == LB_NUM) { Lab.vv.LBLTyp = result->typ; } // 设置标号类型
if(Lab.RefSeg != NULL && Lab.RefSeg != result->rseg )
{ masm.OutWarning(LBLSegNotMatchWarn); } // endif
Lab.RefSeg = result->rseg; // 强制转换参考段
if(Lab.RefSeg) { Lab.Attrb = result->rel; } // endif 从计算结果中获得rel.('A','R')
else { Lab.Attrb = 'A'; } // end else 无参考段的,必不可重定位。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -