📄 macromanager_c.cpp
字号:
//---------------------------------------------------------------------------
// MacroManager_C.cpp
//---------------------------------------------------------------------------
#include "JsGlobal_H.h"
#include "AsmF_H.h"
#include "MacroManager_H.h"
#include "MAsmber_H.h"
//---------------------------------------------------------------------------
//
// 宏指令处理器
//
//---------------------------------------------------------------------------
#define DebugKit(str) DebugMsg(str)
//---------------------------------------------------------------------------
// MacrosManager
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 寻找LOCAL语句。有局参则改成ArgvWordkn。
// 输入局参指针LocalarguPt,返回被赋值后的局参链头指针。
// 输入原有名字链的指针PreNamesSetPt。(可以为NULL。)
// Ln不能为空。 Ln带值返回。返回时Ln指向LOCAL的下一行。
// 错误已印出。
//---------------------------------------------------------------------------
ERR MacrosManager::TryLocalParse( AsmLine* &Ln,
Tokenfield* &LocalarguPt,
Tokenfield* PreNamesSetPt )
{ LocalarguPt = NULL; // 局参指针清零。
Tokenfield* lpt = Ln->FirstTkn();
// lpt->Token == LOCAL ?
if(lpt->Token != WordSToken || lpt->Name != "LOCAL")
{ return OK_no_Err; } // endif 没有找到LOCAL。
// Yes, it is LOCAL!
lpt->Token = LOCALTkn;
Tokenfield* pt = lpt; // Now, pt->next -> 第一个LOCAL标号或者NULL.
if( !lpt->next ) // <==> lpt == NULL
{ masm.OutputErr(MissLocalIDErr); return Have_Errs; } // endif
while( pt->next ) // ... ',' + Word ....
{ ERR err = TokenOper::ArgvWordParser(pt); // 看它是不是一个WordList。
if(err)
{ masm.OutputErr(err); return Have_Errs; } // endif
// No error.
pt = pt->next;
// Now pt->Token == WordSToken
if(TokenOper::HaveArguName(PreNamesSetPt, pt)) // 参数有重名!
{ masm.OutputErr(MacroArgvDupErr); return Have_Errs; } // endif
if(TokenOper::HaveArguName(lpt, pt)) // 参数有重名!
{ masm.OutputErr(MacroArgvDupErr); return Have_Errs; } // endif
// 至此,第一个参数OK。
pt->Token = ArgvWordkn; // Token 进化!
} // end while
LocalarguPt = lpt->next; // 设置局参指针!
Ln = Ln->next; // 此处修改了CLine!! 使它指向宏体头。
return OK_no_Err;
} // end TryLocalParse
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// MroName MACRO ArgvWordkn,ArgvWordkn,ArgvWordkn...
// 对MacroDef后的形参进行语法检查。必须全部是WordSToken,不能有重名。
// 将其改成ArgvWordkn。
// 输入CLine。CLine 必须是MacroDef所在行。
// 该函数会修改CLine!!
//---------------------------------------------------------------------------
ERR MacrosManager::MacroDefParser(AsmLine* &CLine, MacroDefBody* Mbody)
{ Tokenfield* mpt = CLine->FirstTkn(); // mpt->Token == MacroDefkn。
Tokenfield* pt = mpt; // mpt 指向 MACRO Name。
ERR err;
while( pt->next ) // ... ',' + Word ....
{ err = TokenOper::ArgvWordParser(pt);
if(err) { masm.OutputErr(err); return Have_Errs; } // endif
// No error.
pt = pt->next;
// Now pt->Token == WordSToken
if(TokenOper::HaveArguName(mpt, pt)) // 参数有重名!
{ masm.OutputErr(MacroArgvDupErr); return Have_Errs; } // endif
// 至此,第一个参数OK。
pt->Token = ArgvWordkn; // Token 进化!
} // end while
Mbody->arguPtr = mpt->next; // 设置形参指针!
CLine = CLine->next; // 此处修改了CLine !! 使它指向宏体头。
// CLine 不应为NULL。
// 寻找LOCAL并进行语法分析。最后CLine指向LOCAL的下一行。
return TryLocalParse(CLine, Mbody->localPtr, mpt);
} // end MacroDefParser
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 登记宏体。MACRO ...... ENDM
// 输入一个汇编行,该汇编行含有一个MacroDef和一些形参。
// 把该汇编行所含的宏定义登记在宏表中。建立宏体定义。
// 它会修改CLine。通常是用masm->Ln来输入。
// 返回的CLine应该是最外层的ENDM所在的行。
//---------------------------------------------------------------------------
ERR MacrosManager::MacroRegister(AsmLine* &CLine)
{ Tokenfield* pt = CLine->FirstTkn();
if(pt->Token != MacroDefkn) // 在MACRO定义前面不应有标号。
{ masm.OutputErr(IllLBforMroErr); return Have_Errs; } // endif
CLine->Enable = false; // 禁用CLine(MACRO)。
MacroDefBody* mt = MRList->SearchMacro(pt->Name);
if( mt ) // <==> mt != NULL, 有重名!
{ masm.OutputErr(MacroDuplicateErr); return Have_Errs; } // endif
// 经查,没有发现重名。( mt == NULL。)
MacroDefBody* NewMroBody = new MacroDefBody(pt->Name); // 创建新宏定义体
// 对其后的形参进行语法检查。必须全部是WordSToken,不能有重名。
// 如果有LOCAL,也对其后的形参进行语法检查。Token进化。
// CLine = MacroDefkn
if( MacroDefParser(CLine, NewMroBody) ) // 如果宏定义中有语法错误
{ delete NewMroBody; return Have_Errs; } // endif
// 修改了CLine ~~! 也修改了NewMroBody结点的内容!!
// 扫描宏体,识别其中的形参和局参,改成FormalArgv和LocalArgv。
NewMroBody->MroBodyScanAndRecg(CLine); // 找出宏头。找出宏尾。
// CLine 和 NewMroBody 都带值返回。
// 新宏结点插入宏定义表中。
MRList->InsertMacro(NewMroBody);
DebugKit(printf("\nAdd macro def[%s].",(const char*)NewMroBody->MacroName););
return OK_no_Err;
} // end MacroRegister
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 把宏定义体中的某一行拿出来,把其中的形参用实参替代。
// 产生一个字串(len<255),返回该字串。
//---------------------------------------------------------------------------
ERR MacrosManager::MacroLineBacktoJstr(AsmLine* Line, Jstring &s)
{ s = "";
for( Tokenfield* pt = Line->FirstTkn();
pt;
pt = pt->next )
{ switch(pt->Token)
{ case FormalArgv: // 形参
{ register Tokenfield* t = pt->ExpPt->ExpPt; // !!!
if(t) { pt->Name = t->Name; } // endif
else { pt->Name = ""; } // endif
break;
} // end case
case LocalArgv : // 局参
{ LocalArgvToJstr((int16u)pt->ExpPt->Value, pt->Name);
break;
} // end case
// no default...
} // end switch
} // end for
for( Tokenfield* pt = Line->FirstTkn();
pt;
pt = pt->next )
{ s += pt->Name;
if(pt->next)
{ switch(pt->Token)
{ case WordSToken: case FormalArgv: case LocalArgv:
{ switch(pt->next->Token)
{ case WordSToken: case FormalArgv: case LocalArgv: case '@':
{ s = s + " "; break; } // end case
case txtCATtxt:
{ pt = pt->next; break; } // end case
} // end switch
break;
} // end case
} // end switch
} // endif
} // end for
if(s.getLen() > 255)
{ masm.OutputErr(LenExcesMroErr); return Have_Errs; } // endif
return OK_no_Err;
} // end MacroLineBacktoJstr
//---------------------------------------------------------------------------
const MaxNest_MACRO_SUM = 99;
//---------------------------------------------------------------------------
// 宏展开词法分析器。
// 给宏定义体初始化好形参和局参后,把宏展开,并进行词法分析。
// masm->Ln受影响,Ln是宏调用所在汇编行。重要!
// 返回的err是用来送向OutputErr()的。
//---------------------------------------------------------------------------
ERR MacrosManager::MacroToToken( const MacroDefBody* mbody, // 要展开的宏定义体。
AsmLine* BaseLn, // 基准行。
AsmLine* InsLn, // 插入行。
AsmLine* &CLn ) // 用于返回最后展开行。
{ ERR erra = OK_no_Err;
bool CommentEnable = false;
AsmLine* &Ln = masm.Ln; // Attention!!
AsmFile* &AsmFn = masm.AsmFn;
if(Ln->NestNo >= MaxNest_MACRO_SUM) // 宏嵌套超过最高层数!
{ return MroCallNestOutErr; } // endif
CLn = InsLn; // CLn 指向宏调用所在汇编行, 它用于记录插入点。
Jstring s;
for( AsmLine* ln = mbody->MacroBegin;
ln != mbody->MacroEnd;
ln = ln->next )
{ // ..................................................................
erra = MacroLineBacktoJstr(ln, s); // 把宏中的一行转换成字串。得到s。
if(erra) { break; } // endif Break from for
DebugKit(printf("\ns=[%s]", (const char*)s); Debugkey;);
// Now, 得到一个Strings s.
Ln = new AsmLine; // 创建新汇编行对象
Ln->LineNo = BaseLn->LineNo; // 给新行赋行号值
Ln->NestNo = BaseLn->NestNo + 1; //
Ln->head->Name = s; // 该汇编行的头结点上有展开的宏字串。
char ts[256];
Jassert(s.getLen()<255);
ERR err = masm.StrLexToAsmline(s.makeStr(ts), Ln, CommentEnable);
// 把一行转换成Token流。
if(err == 1) { erra = Have_Errs; } // endif
// err maybe == 2 or 0.
if(Ln->TknLNotEmpty()) // 如果不是只有一个头结点的话
{ AsmFn->InsertAsmLine(Ln, CLn); // 在CLn后插入。
CLn = Ln; // 更新CLn的值。
} // endif // 汇编行加进AsmFile中。
else // 只有一个头结点的汇编行不添加到AsmFile中.
{ delete Ln; Ln = NULL; } // end else
// ..................................................................
} // end for
Ln = InsLn; // 重置Ln。
return erra;
} // end MacroToToken
//---------------------------------------------------------------------------
const int16u MaxMroCallSum = 60000;
//---------------------------------------------------------------------------
// 宏调用处理。处理宏替代。
// Ln受影响。Ln为宏调用所在汇编行。
//---------------------------------------------------------------------------
ERR MacrosManager::MacroCall(AsmLine* &Ln)
{ if(++MacroCallCounter > MaxMroCallSum)
{ FatalErr("\nMacro calling nested too deep or too many macros!"); } // endif
Tokenfield* pt = Ln->FirstTkn(); // pt->Token should be MacroRefkn.
for( ; pt && pt->Token != MacroRefkn; pt = pt->next ); // end for
Tokenfield* MDefPt = pt; // 保存宏调用结点指针。
MacroDefBody* mbody = pt->MacroPt; // 得到该宏对应的宏定义体。
// 把实参代入形参。实参个数可能少于形参个数。
pt = pt->next; // Now, pt->Token should be MroParamtn.
register Tokenfield* gt = mbody->arguPtr;
for( ; gt && pt; gt = gt->next, pt = pt->next )
{ //..................................................
Assert( if(pt->Token != MroParamtn) // Just for debug!!
{ printf("\nBugs in MacroCall!"); Debugkey; } // endif
);
//..................................................
gt->ExpPt = pt; // 宏定义体中的形参指针指向实参Token!!
} // end for
if( gt ) // 实参个数少于形参个数。
{ masm.OutWarning(InsufParaMroWarn);
for( ; gt; gt = gt->next) // 给每个未赋值的形参赋NUL。
{ gt->ExpPt = NULL; } // end for
} // endif
// 给局参赋值。
for( gt = mbody->localPtr; gt; gt = gt->next )
{ gt->Value = AssaignLocalLabelNo(); } // end for
// 给宏定义体初始化好形参和局参后,送宏展开,词法分析器。
AsmLine* LastLn;
ERR err = MacroToToken(mbody,Ln,Ln,LastLn);
if(err) { masm.OutputErr(MacroLexErr); return err; } // endif
// Now, Ln仍然为宏调用所在汇编行。
TokenOper::DelTokenList(MDefPt->next); // 宏完全展开后,把宏调用之后指令删除。
MDefPt->Token = MroCalling; // Token进化!
return err;
} // end MacroCall
//---------------------------------------------------------------------------
#undef FatalErrPrn
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// REPT 语法分析器。
// 它返回REPT重复的次数。
//---------------------------------------------------------------------------
int16u MacrosManager::REPT_Parser(ERR &err, AsmLine* Ln)
{ err = OK_no_Err;
Tokenfield* pt = Ln->head;
for( ; pt && pt->Token != REPTTkn; pt = pt->next ); // end for
// Now, pt == REPTTkn or NULL
// pt->next should be a Expr. or NULL.
// Need Only One Expr
int8 count = TokenOper::CalExpNum(pt, err);
if(err) { return 0; } // endif
switch(count)
{ case 0 : { err = ArguInsufErr; return 0; } // end case
case 1 : { break; } // end case
default: { err = ArguInsufErr; return 0; } // end case
} // end switch
// Now, pt 指向REPT Token。
const TriVal* trv
= masm.LabMger->CalExpression(err,pt->next->ExpPt); // 带回err。
if(err) { err = BadExptReptErr; return 0; } // 该行异常终止
// No error.
pt->Token = ReptDefkn; // Token进化!!
pt->Value = trv->val; // 该结果暂存在REPT Token的Value域中。
// 得到了一个数值。检查数值范围。(0 ~ 65535)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -