⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 labelmaniger_c.cpp

📁 MCS51单片机的宏汇编器源程序。有需要的朋友请下载!
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//---------------------------------------------------------------------------
//   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 + -