📄 preproc.c
字号:
size = MAX(StackSize, 10);
}
else
{
error(ERR_NONFATAL,
"Invalid size type for `%%local' missing directive");
free_tlist(tt);
free_tlist(origline);
return DIRECTIVE_FOUND;
}
free_tlist(tt);
/* Now define the macro for the argument */
sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
offset);
do_directive(tokenise(directive));
offset += size;
/* Now define the assign to setup the enter_c macro correctly */
sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
size);
do_directive(tokenise(directive));
/* Move to the next argument in the list */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
}
while (tline && tline->type == TOK_OTHER
&& tline->text[0] == ',');
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_CLEAR:
if (tline->next)
error(ERR_WARNING,
"trailing garbage after `%%clear' ignored");
for (j = 0; j < NHASH; j++)
{
while (mmacros[j])
{
MMacro *m = mmacros[j];
mmacros[j] = m->next;
free_mmacro(m);
}
while (smacros[j])
{
SMacro *s = smacros[j];
smacros[j] = smacros[j]->next;
nasm_free(s->name);
free_tlist(s->expansion);
nasm_free(s);
}
}
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_INCLUDE:
tline = tline->next;
skip_white_(tline);
if (!tline || (tline->type != TOK_STRING &&
tline->type != TOK_INTERNAL_STRING))
{
error(ERR_NONFATAL, "`%%include' expects a file name");
free_tlist(origline);
return DIRECTIVE_FOUND; /* but we did _something_ */
}
if (tline->next)
error(ERR_WARNING,
"trailing garbage after `%%include' ignored");
if (tline->type != TOK_INTERNAL_STRING)
{
p = tline->text + 1; /* point past the quote to the name */
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
}
else
p = tline->text; /* internal_string is easier */
expand_macros_in_string(&p);
inc = nasm_malloc(sizeof(Include));
inc->next = istk;
inc->conds = NULL;
inc->fp = inc_fopen(p);
inc->fname = src_set_fname(p);
inc->lineno = src_set_linnum(0);
inc->lineinc = 1;
inc->expansion = NULL;
inc->mstk = NULL;
istk = inc;
list->uplevel(LIST_INCLUDE);
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_PUSH:
tline = tline->next;
skip_white_(tline);
tline = expand_id(tline);
if (!tok_type_(tline, TOK_ID))
{
error(ERR_NONFATAL, "`%%push' expects a context identifier");
free_tlist(origline);
return DIRECTIVE_FOUND; /* but we did _something_ */
}
if (tline->next)
error(ERR_WARNING, "trailing garbage after `%%push' ignored");
ctx = nasm_malloc(sizeof(Context));
ctx->next = cstk;
ctx->localmac = NULL;
ctx->name = nasm_strdup(tline->text);
ctx->number = unique++;
cstk = ctx;
free_tlist(origline);
break;
case PP_REPL:
tline = tline->next;
skip_white_(tline);
tline = expand_id(tline);
if (!tok_type_(tline, TOK_ID))
{
error(ERR_NONFATAL, "`%%repl' expects a context identifier");
free_tlist(origline);
return DIRECTIVE_FOUND; /* but we did _something_ */
}
if (tline->next)
error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
if (!cstk)
error(ERR_NONFATAL, "`%%repl': context stack is empty");
else
{
nasm_free(cstk->name);
cstk->name = nasm_strdup(tline->text);
}
free_tlist(origline);
break;
case PP_POP:
if (tline->next)
error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
if (!cstk)
error(ERR_NONFATAL,
"`%%pop': context stack is already empty");
else
ctx_pop();
free_tlist(origline);
break;
case PP_ERROR:
tline->next = expand_smacro(tline->next);
tline = tline->next;
skip_white_(tline);
if (tok_type_(tline, TOK_STRING))
{
p = tline->text + 1; /* point past the quote to the name */
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
expand_macros_in_string(&p);
error(ERR_NONFATAL, "%s", p);
nasm_free(p);
}
else
{
p = detoken(tline, FALSE);
error(ERR_WARNING, "%s", p);
nasm_free(p);
}
free_tlist(origline);
break;
case PP_IF:
case PP_IFCTX:
case PP_IFDEF:
case PP_IFID:
case PP_IFIDN:
case PP_IFIDNI:
case PP_IFMACRO:
case PP_IFNCTX:
case PP_IFNDEF:
case PP_IFNID:
case PP_IFNIDN:
case PP_IFNIDNI:
case PP_IFNMACRO:
case PP_IFNNUM:
case PP_IFNSTR:
case PP_IFNUM:
case PP_IFSTR:
if (istk->conds && !emitting(istk->conds->state))
j = COND_NEVER;
else
{
j = if_condition(tline->next, i);
tline->next = NULL; /* it got freed */
free_tlist(origline);
j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
}
cond = nasm_malloc(sizeof(Cond));
cond->next = istk->conds;
cond->state = j;
istk->conds = cond;
return DIRECTIVE_FOUND;
case PP_ELIF:
case PP_ELIFCTX:
case PP_ELIFDEF:
case PP_ELIFID:
case PP_ELIFIDN:
case PP_ELIFIDNI:
case PP_ELIFMACRO:
case PP_ELIFNCTX:
case PP_ELIFNDEF:
case PP_ELIFNID:
case PP_ELIFNIDN:
case PP_ELIFNIDNI:
case PP_ELIFNMACRO:
case PP_ELIFNNUM:
case PP_ELIFNSTR:
case PP_ELIFNUM:
case PP_ELIFSTR:
if (!istk->conds)
error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
if (emitting(istk->conds->state)
|| istk->conds->state == COND_NEVER)
istk->conds->state = COND_NEVER;
else
{
/*
* IMPORTANT: In the case of %if, we will already have
* called expand_mmac_params(); however, if we're
* processing an %elif we must have been in a
* non-emitting mode, which would have inhibited
* the normal invocation of expand_mmac_params(). Therefore,
* we have to do it explicitly here.
*/
j = if_condition(expand_mmac_params(tline->next), i);
tline->next = NULL; /* it got freed */
free_tlist(origline);
istk->conds->state =
j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
}
return DIRECTIVE_FOUND;
case PP_ELSE:
if (tline->next)
error(ERR_WARNING, "trailing garbage after `%%else' ignored");
if (!istk->conds)
error(ERR_FATAL, "`%%else': no matching `%%if'");
if (emitting(istk->conds->state)
|| istk->conds->state == COND_NEVER)
istk->conds->state = COND_ELSE_FALSE;
else
istk->conds->state = COND_ELSE_TRUE;
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_ENDIF:
if (tline->next)
error(ERR_WARNING,
"trailing garbage after `%%endif' ignored");
if (!istk->conds)
error(ERR_FATAL, "`%%endif': no matching `%%if'");
cond = istk->conds;
istk->conds = cond->next;
nasm_free(cond);
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_MACRO:
case PP_IMACRO:
if (defining)
error(ERR_FATAL,
"`%%%smacro': already defining a macro",
(i == PP_IMACRO ? "i" : ""));
tline = tline->next;
skip_white_(tline);
tline = expand_id(tline);
if (!tok_type_(tline, TOK_ID))
{
error(ERR_NONFATAL,
"`%%%smacro' expects a macro name",
(i == PP_IMACRO ? "i" : ""));
return DIRECTIVE_FOUND;
}
defining = nasm_malloc(sizeof(MMacro));
defining->name = nasm_strdup(tline->text);
defining->casesense = (i == PP_MACRO);
defining->plus = FALSE;
defining->nolist = FALSE;
defining->in_progress = FALSE;
defining->rep_nest = NULL;
tline = expand_smacro(tline->next);
skip_white_(tline);
if (!tok_type_(tline, TOK_NUMBER))
{
error(ERR_NONFATAL,
"`%%%smacro' expects a parameter count",
(i == PP_IMACRO ? "i" : ""));
defining->nparam_min = defining->nparam_max = 0;
}
else
{
defining->nparam_min = defining->nparam_max =
readnum(tline->text, &j);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
tline->text);
}
if (tline && tok_is_(tline->next, "-"))
{
tline = tline->next->next;
if (tok_is_(tline, "*"))
defining->nparam_max = INT_MAX;
else if (!tok_type_(tline, TOK_NUMBER))
error(ERR_NONFATAL,
"`%%%smacro' expects a parameter count after `-'",
(i == PP_IMACRO ? "i" : ""));
else
{
defining->nparam_max = readnum(tline->text, &j);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
tline->text);
if (defining->nparam_min > defining->nparam_max)
error(ERR_NONFATAL,
"minimum parameter count exceeds maximum");
}
}
if (tline && tok_is_(tline->next, "+"))
{
tline = tline->next;
defining->plus = TRUE;
}
if (tline && tok_type_(tline->next, TOK_ID) &&
!nasm_stricmp(tline->next->text, ".nolist"))
{
tline = tline->next;
defining->nolist = TRUE;
}
mmac = mmacros[hash(defining->name)];
while (mmac)
{
if (!strcmp(mmac->name, defining->name) &&
(mmac->nparam_min <= defining->nparam_max
|| defining->plus)
&& (defining->nparam_min <= mmac->nparam_max
|| mmac->plus))
{
error(ERR_WARNING,
"redefining multi-line macro `%s'",
defining->name);
break;
}
mmac = mmac->next;
}
/*
* Handle default parameters.
*/
if (tline && tline->next)
{
defining->dlist = tline->next;
tline->next = NULL;
count_mmac_params(defining->dlist, &defining->ndefs,
&defining->defaults);
}
else
{
defining->dlist = NULL;
defining->defaults = NULL;
}
defining->expansion = NULL;
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_ENDM:
case PP_ENDMACRO:
if (!defining)
{
error(ERR_NONFATAL, "`%s': not defining a macro",
tline->text);
return DIRECTIVE_FOUND;
}
k = hash(defining->name);
defining->next = mmacros[k];
mmacros[k] = defining;
defining = NULL;
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_ROTATE:
if (tline->next && tline->next->type == TOK_WHITESPACE)
tline = tline->next;
if (tline->next == NULL)
{
free_tlist(origline);
error(ERR_NONFATAL, "`%%rotate' missing rotate count");
return DIRECTIVE_FOUND;
}
t = expand_smacro(tline->next);
tline->next = NULL;
free_tlist(origline);
tline = t;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
evalresult =
evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
free_tlist(tline);
if (!evalresult)
return DIRECTIVE_FOUND;
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
if (!is_simple(evalresult))
{
error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
return DIRECTIVE_FOUND;
}
mmac = istk->mstk;
while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
mmac = mmac->next_active;
if (!mmac)
{
error(ERR_NONFATAL,
"`%%rotate' invoked outside a macro call");
}
else if (mmac->nparam == 0)
{
error(ERR_NONFATAL,
"`%%rotate' invoked within macro without parameters");
}
else
{
mmac->rotate = mmac->rotate + reloc_value(evalresult);
if (mmac->rotate < 0)
mmac->rotate =
mmac->nparam - (-mmac->rotate) % mmac->nparam;
mmac->rotate %= mmac->nparam;
}
return DIRECTIVE_FOUND;
case PP_REP:
nolist = FALSE;
do {
tline = tline->next;
} while (tok_type_(tline, TOK_WHITESPACE));
if (tok_type_(tline, TOK_ID) &&
nasm_stricmp(tline->text, ".nolist") == 0)
{
nolist = TRUE;
do {
tline = tline->next;
} while (tok_type_(tline, TOK_WHITESPACE));
}
if (tline)
{
t = expand_smacro(tline);
tptr = &t;
tokval.t_type = TOKEN_INVALID;
evalresult =
evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
if (!evalresult)
{
free_tlist(origline);
return DIRECTIVE_FOUND;
}
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
if (!is_simple(evalresult))
{
error(ERR_NONFATAL, "non-constant value given to `%%rep'");
return DIRECTIVE_FOUND;
}
i = (int)reloc_value(evalresult) + 1;
}
else
{
error(ERR_NONFATAL, "`%%rep' expects a repeat count");
i = 0;
}
free_tlist(origline);
tmp_defining = defining;
defining = nasm_malloc(sizeof(MMacro));
defining->name = NULL; /* flags this macro as a %rep block */
defining->casesense = 0;
defining->plus = FALSE;
defining->nolist = nolist;
defining->in_progress = i;
defining->nparam_min = defining->nparam_max = 0;
defining->defaults = NULL;
defining->dlist = NULL;
defining->expansion = NULL;
defining->next_active = istk->mstk;
defining->rep_nest = tmp_defining;
return DIRECTIVE_FOUND;
case PP_ENDREP:
if (!defining || defining->name)
{
error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
return DIRECTIVE_FOUND;
}
/*
* Now we ha
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -