函数流程
-
/*
-
* Expand all single-line macro calls made in the given line.
-
* Return the expanded version of the line. The original is deemed
-
* to be destroyed in the process. (In reality we'll just move
-
* Tokens from input to output a lot of the time, rather than
-
* actually bothering to destroy and replicate.)
-
*/
-
static Token *expand_smacro(Token * tline)
-
{
-
Token *t, *tt, *mstart, **tail, *thead;
-
SMacro *head = NULL, *m;
-
Token **params;
-
int *paramsize;
-
int nparam, sparam, brackets, rescan;
-
Token *org_tline = tline;
-
Context *ctx;
-
char *mname;
-
-
/*
-
* Trick: we should avoid changing the start token pointer since it can
-
* be contained in "next" field of other token. Because of this
-
* we allocate a copy of first token and work with it; at the end of
-
* routine we copy it back
-
*/
-
if (org_tline) {
-
tline = new_Token(org_tline->next, org_tline->type, org_tline->text, 0);
-
tline->mac = org_tline->mac;
-
nasm_free(org_tline->text);
-
org_tline->text = NULL;
-
}
-
-
again:
-
tail = &thead;
-
thead = NULL;
-
-
while (tline)
-
{ /* main token loop */
-
if ((mname = tline->text))
-
{
-
/* 获取与tline->text相关的宏 */
-
/* if this token is a local macro, look in local context */
-
if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
-
ctx = get_ctx(mname, TRUE);
-
else
-
ctx = NULL;
-
if (!ctx)
-
head = smacros[hash(mname)];
-
else
-
head = ctx->localmac;
-
/*
-
* We've hit an identifier. As in is_mmacro below, we first
-
* check whether the identifier is a single-line macro at
-
* all, then think about checking for parameters if
-
* necessary.
-
*/
-
for (m = head; m; m = m->next)
-
{
-
if (!mstrcmp(m->name, mname, m->casesense))
-
break;
-
}
-
-
/* 如果存在与tline->text相关的宏 */
-
if (m)
-
{
-
mstart = tline;
-
params = NULL;
-
paramsize = NULL;
-
if (m->nparam == 0)
-
{
-
/*
-
* Simple case: the macro is parameterless. Discard the
-
* one token that the macro call took, and push the
-
* expansion back on the to-do stack.
-
*/
-
if (!m->expansion)
-
{
-
/* 处理Nasm预先定义的宏__FILE__ */
-
if (!strcmp("__FILE__", m->name))
-
{
-
long num = 0;
-
src_get(&num, &(tline->text));
-
nasm_quote(&(tline->text));
-
tline->type = TOK_STRING;
-
continue;
-
}
-
/* 处理Nasm预先定义的宏__LINE__ */
-
if (!strcmp("__LINE__", m->name))
-
{
-
nasm_free(tline->text);
-
make_tok_num(tline, src_get_linnum());
-
continue;
-
}
-
/* 空宏 */
-
tline = delete_Token(tline);
-
continue;
-
}
-
}
-
else
-
{
-
/*
-
* Complicated case: at least one macro with this name
-
* exists and takes parameters. We must find the
-
* parameters in the call, count them, find the SMacro
-
* that corresponds to that form of the macro call, and
-
* substitute for the parameters when we expand. What a
-
* pain.
-
*/
-
/* tline = tline->next;
-
skip_white_(tline); */
-
do {
-
t = tline->next;
-
/* ????? */
-
while (tok_type_(t, TOK_SMAC_END)) {
-
t->mac->in_progress = FALSE;
-
t->text = NULL;
-
t = tline->next = delete_Token(t);
-
}
-
tline = t;
-
} while (tok_type_(tline, TOK_WHITESPACE));
-
if (!tok_is_(tline, "("))
-
{
-
/*
-
* This macro wasn't called with parameters: ignore
-
* the call. (Behaviour borrowed from gnu cpp.)
-
*/
-
tline = mstart;
-
m = NULL;
-
}
-
else /* '(',处理宏参数 */
-
{
-
int paren = 0;
-
int white = 0;
-
brackets = 0;
-
nparam = 0;
-
sparam = PARAM_DELTA;
-
params = nasm_malloc(sparam * sizeof(Token *));
-
params[0] = tline->next;
-
paramsize = nasm_malloc(sparam * sizeof(int));
-
paramsize[0] = 0;
-
/* 正式处理宏参数,将宏参数放入params中,并且计算宏参数的个数 */
-
while (TRUE) { /* parameter loop */
-
/*
-
* For some unusual expansions
-
* which concatenates function call
-
*/
-
t = tline->next;
-
/* ????? */
-
while (tok_type_(t, TOK_SMAC_END)) {
-
t->mac->in_progress = FALSE;
-
t->text = NULL;
-
t = tline->next = delete_Token(t);
-
}
-
tline = t;
-
-
if (!tline) {
-
error(ERR_NONFATAL, "macro call expects terminating `)'");
-
break;
-
}
-
if (tline->type == TOK_WHITESPACE && brackets <= 0) {
-
if (paramsize[nparam])
-
white++;
-
else
-
params[nparam] = tline->next;
-
continue; /* parameter loop */
-
}
-
if (tline->type == TOK_OTHER && tline->text[1] == 0) /* 判断是否是单字符 */
-
{
-
char ch = tline->text[0];
-
if (ch == ',' && !paren && brackets <= 0) { /* 处理完一个参数 */
-
if (++nparam >= sparam) { /* 如果原有的数据不够,重新分配缓存 */
-
sparam += PARAM_DELTA;
-
params = nasm_realloc(params, sparam * sizeof(Token *));
-
paramsize = nasm_realloc(paramsize, sparam * sizeof(int));
-
}
-
params[nparam] = tline->next;
-
paramsize[nparam] = 0;
-
white = 0;
-
continue; /* parameter loop */
-
}
-
if (ch == '{' && (brackets > 0 || (brackets == 0 && !paramsize[nparam])))
-
{
-
if (!(brackets++)) {
-
params[nparam] = tline->next; /* 去掉'{' */
-
continue; /* parameter loop */
-
}
-
}
-
if (ch == '}' && brackets > 0)
-
if (--brackets == 0) {
-
brackets = -1; /* 单行宏参数中不能使用'{' 和 '}',去掉 '}' */
-
continue; /* parameter loop */
-
}
-
if (ch == '(' && !brackets)
-
paren++;
-
if (ch == ')' && brackets <= 0)
-
if (--paren < 0)
-
break;
-
}
-
if (brackets < 0) {
-
brackets = 0;
-
error(ERR_NONFATAL, "braces do not enclose all of macro parameter");
-
}
-
paramsize[nparam] += white + 1;
-
white = 0;
-
} /* parameter loop */
-
nparam++;
-
while (m && (m->nparam != nparam || mstrcmp(m->name, mname, m->casesense))) /* 处理同名宏不同参数的情况,找到相应的宏 */
-
m = m->next;
-
if (!m)
-
error(ERR_WARNING | ERR_WARN_MNP, "macro `%s' exists, but not taking %d parameters", mstart->text, nparam);
-
}
-
}
-
if (m && m->in_progress)
-
m = NULL;
-
if (!m) { /* in progess or didn't find '(' or wrong nparam */
-
/*
-
* Design question: should we handle !tline, which
-
* indicates missing ')' here, or expand those
-
* macros anyway, which requires the (t) test a few
-
* lines down?
-
*/
-
nasm_free(params);
-
nasm_free(paramsize);
-
tline = mstart;
-
} else {
-
/*
-
* Expand the macro: we are placed on the last token of the
-
* call, so that we can easily split the call from the
-
* following tokens. We also start by pushing an SMAC_END
-
* token for the cycle removal.
-
*/
-
t = tline;
-
if (t) {
-
tline = t->next;
-
t->next = NULL;
-
}
-
tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
-
tt->mac = m;
-
m->in_progress = TRUE;
-
tline = tt;
-
/* 真实的参数扩展 */
-
for (t = m->expansion; t; t = t->next) {
-
if (t->type >= TOK_SMAC_PARAM) {
-
Token *pcopy = tline, **ptail = &pcopy;
-
Token *ttt, *pt;
-
int i;
-
-
ttt = params[t->type - TOK_SMAC_PARAM]; /* 获取实参 */
-
for (i = paramsize[t->type - TOK_SMAC_PARAM]; --i >= 0;) {
-
pt = *ptail = new_Token(tline, ttt->type, ttt->text, 0);
-
ptail = &pt->next;
-
ttt = ttt->next;
-
}
-
tline = pcopy;
-
} else {
-
tt = new_Token(tline, t->type, t->text, 0);
-
tline = tt;
-
}
-
}
-
-
/*
-
* Having done that, get rid of the macro call, and clean
-
* up the parameters.
-
*/
-
nasm_free(params);
-
nasm_free(paramsize);
-
free_tlist(mstart);
-
continue; /* main token loop */
-
}
-
}
-
}
-
-
if (tline->type == TOK_SMAC_END) {
-
tline->mac->in_progress = FALSE;
-
tline = delete_Token(tline);
-
} else {
-
t = *tail = tline;
-
tline = tline->next;
-
t->mac = NULL;
-
t->next = NULL;
-
tail = &t->next;
-
}
-
}
-
-
/*
-
* Now scan the entire line and look for successive TOK_IDs that resulted
-
* after expansion (they can't be produced by tokenise()). The successive
-
* TOK_IDs should be concatenated.
-
* Also we look for %+ tokens and concatenate the tokens before and after
-
* them (without white spaces in between).
-
*/
-
t = thead;
-
rescan = 0;
-
while (t) {
-
while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
-
t = t->next;
-
if (!t || !t->next)
-
break;
-
/*
-
* %define ADD(a,b) ((a) + (b))
-
* %define ADD(a,b,c) ((a %+ DD(1,2)) + (b) + (c))
-
*
-
* [bits 32]
-
* _start:
-
* mov eax,ADD(1,3)
-
* mov eax,ADD(A,2,3)
-
*/
-
if (t->next->type == TOK_ID ||
-
t->next->type == TOK_PREPROC_ID ||
-
t->next->type == TOK_NUMBER) {
-
char *p = nasm_strcat(t->text, t->next->text);
-
nasm_free(t->text);
-
t->next = delete_Token(t->next);
-
t->text = p;
-
rescan = 1;
-
} else if (t->next->type == TOK_WHITESPACE && t->next->next &&
-
t->next->next->type == TOK_PREPROC_ID &&
-
strcmp(t->next->next->text, "%+") == 0) {
-
/* free the next whitespace, the %+ token and next whitespace */
-
int i;
-
for (i = 1; i <= 3; i++) {
-
if (!t->next
-
|| (i != 2 && t->next->type != TOK_WHITESPACE))
-
break;
-
t->next = delete_Token(t->next);
-
} /* endfor */
-
} else
-
t = t->next;
-
}
-
/* If we concatenaded something, re-scan the line for macros */
-
if (rescan) {
-
tline = thead;
-
goto again;
-
}
-
-
if (org_tline) {
-
if (thead) {
-
*org_tline = *thead;
-
/* since we just gave text to org_line, don't free it */
-
thead->text = NULL;
-
delete_Token(thead);
-
} else {
-
/* the expression expanded to empty line;
-
we can't return NULL for some reasons
-
we just set the line to a single WHITESPACE token. */
-
memset(org_tline, 0, sizeof(*org_tline));
-
org_tline->text = NULL;
-
org_tline->type = TOK_WHITESPACE;
-
}
-
thead = org_tline;
-
}
-
-
return thead;
-
}
阅读(2087) | 评论(0) | 转发(0) |