📄 preproc.c
字号:
/*
* The expression was bogus, but let's make
* %endif not complain about missing %if
*/
j = COND_NEVER;
else
istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
}
return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
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 5;
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 5;
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);
if (!tok_type_(tline, TOK_ID)) {
error (ERR_NONFATAL,
"`%%%smacro' expects a macro name",
(i == PP_IMACRO ? "i" : ""));
return 3;
}
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 = 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 1;
case PP_ENDM:
case PP_ENDMACRO:
if (!defining) {
error (ERR_NONFATAL, "`%s': not defining a macro",
tline->text);
return 3;
}
k = hash(defining->name);
defining->next = mmacros[k];
mmacros[k] = defining;
defining = NULL;
free_tlist (origline);
return 5;
case PP_ROTATE:
if (tline->next && tline->next->type == TOK_WHITESPACE)
tline = tline->next;
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 3;
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 3;
}
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");
mmac->rotate = mmac->rotate + reloc_value(evalresult);
if (mmac->rotate < 0)
mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
mmac->rotate %= mmac->nparam;
return 1;
case PP_REP:
nolist = FALSE;
tline = tline->next;
if (tline->next && tline->next->type == TOK_WHITESPACE)
tline = tline->next;
if (tline->next && tline->next->type == TOK_ID &&
!nasm_stricmp(tline->next->text, ".nolist")) {
tline = tline->next;
nolist = TRUE;
}
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 3;
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 3;
}
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 = reloc_value(evalresult) + 1;
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 1;
case PP_ENDREP:
if (!defining || defining->name) {
error (ERR_NONFATAL,
"`%%endrep': no matching `%%rep'");
return 3;
}
/*
* Now we have a "macro" defined - although it has no name
* and we won't be entering it in the hash tables - we must
* push a macro-end marker for it on to istk->expansion.
* After that, it will take care of propagating itself (a
* macro-end marker line for a macro which is really a %rep
* block will cause the macro to be re-expanded, complete
* with another macro-end marker to ensure the process
* continues) until the whole expansion is forcibly removed
* from istk->expansion by a %exitrep.
*/
l = nasm_malloc(sizeof(Line));
l->next = istk->expansion;
l->finishes = defining;
l->first = NULL;
istk->expansion = l;
istk->mstk = defining;
list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
tmp_defining = defining;
defining = defining->rep_nest;
free_tlist (origline);
return 1;
case PP_EXITREP:
/*
* We must search along istk->expansion until we hit a
* macro-end marker for a macro with no name. Then we set
* its `in_progress' flag to 0.
*/
for (l = istk->expansion; l; l = l->next)
if (l->finishes && !l->finishes->name)
break;
if (l)
l->finishes->in_progress = 0;
else
error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
free_tlist (origline);
return 1;
case PP_DEFINE:
case PP_IDEFINE:
tline = tline->next;
skip_white_(tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
error (ERR_NONFATAL,
"`%%%sdefine' expects a macro identifier",
(i == PP_IDEFINE ? "i" : ""));
free_tlist (origline);
return 3;
}
mname = tline->text;
if (tline->type == TOK_ID) {
p = tline->text;
smhead = &smacros[hash(mname)];
} else {
ctx = get_ctx (tline->text);
if (ctx == NULL)
return 3;
else {
p = tline->text+1;
p += strspn(p, "$");
smhead = &ctx->localmac;
}
}
last = tline;
param_start = tline = tline->next;
nparam = 0;
if (tok_is_(tline, "(")) {
/*
* This macro has parameters.
*/
tline = tline->next;
while (1) {
skip_white_(tline);
if (!tline) {
error (ERR_NONFATAL,
"parameter identifier expected");
free_tlist (origline);
return 3;
}
if (tline->type != TOK_ID) {
error (ERR_NONFATAL,
"`%s': parameter identifier expected",
tline->text);
free_tlist (origline);
return 3;
}
tline->type = TOK_SMAC_PARAM + nparam++;
tline = tline->next;
skip_white_(tline);
if (tok_is_(tline, ",")) {
tline = tline->next;
continue;
}
if (!tok_is_(tline, ")")) {
error (ERR_NONFATAL,
"`)' expected to terminate macro template");
free_tlist (origline);
return 3;
}
break;
}
last = tline;
tline = tline->next;
}
if (tok_type_(tline, TOK_WHITESPACE))
last = tline, tline = tline->next;
macro_start = NULL;
last->next = NULL;
t = tline;
while (t) {
if (t->type == TOK_ID) {
for (tt = param_start; tt; tt = tt->next)
if (tt->type >= TOK_SMAC_PARAM &&
!strcmp(tt->text, t->text))
t->type = tt->type;
}
tt = t->next;
t->next = macro_start;
macro_start = t;
t = tt;
}
/*
* Good. We now have a macro name, a parameter count, and a
* token list (in reverse order) for an expansion. We ought
* to be OK just to create an SMacro, store it, and let
* free_tlist have the rest of the line (which we have
* carefully re-terminated after chopping off the expansion
* from the end).
*/
if (smacro_defined (mname, nparam, &smac, i==PP_DEFINE)) {
if (!smac) {
error (ERR_WARNING,
"single-line macro `%s' defined both with and"
" without parameters", mname);
free_tlist (origline);
free_tlist (macro_start);
return 3;
} else {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
* what was already in it.
*/
nasm_free (smac->name);
free_tlist (smac->expansion);
}
} else {
smac = nasm_malloc(sizeof(SMacro));
smac->next = *smhead;
*smhead = smac;
}
smac->name = nasm_strdup(p);
smac->casesense = (i == PP_DEFINE);
smac->nparam = nparam;
smac->expansion = macro_start;
smac->in_progress = FALSE;
free_tlist (origline);
return 3;
case PP_UNDEF:
tline = tline->next;
skip_white_(tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
error (ERR_NONFATAL,
"`%%undef' expects a macro identifier");
free_tlist (origline);
return 3;
}
mname = tline->text;
if (tline->type == TOK_ID) {
p = tline->text;
smhead = &smacros[hash(mname)];
} else {
ctx = get_ctx (tline->text);
if (ctx == NULL) {
free_tlist (origline);
return 3;
} else {
p = tline->text+1;
p += strspn(p, "$");
smhead = &ctx->localmac;
}
}
last = tline;
tline = tline->next;
last->next = NULL;
if (tline)
error(ERR_WARNING,
"trailing garbage after macro name ignored");
/*
* We now have a macro name... go hunt for it.
*/
while (smacro_defined (mname, -1, &smac, 1)) {
/* Defined, so we need to find its predecessor and nuke it */
SMacro **s;
for ( s = smhead ; *s && *s != smac ; s = &(*s)->next );
if ( *s ) {
*s = smac->next;
nasm_free(smac->name);
free_tlist(smac->expansion);
nasm_free(smac);
}
}
return 3;
case PP_ASSIGN:
case PP_IASSIGN:
tline = tline->next;
skip_white_(tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
error (ERR_NONFATAL,
"`%%%sassign' expects a macro identifier",
(i == PP_IASSIGN ? "i" : ""));
free_tlist (origline);
return 3;
}
mname = tline->text;
if (tline->type == TOK_ID) {
p = tline->text;
smhead = &smacros[hash(mname)];
} else {
ctx = get_ctx (tline->text);
if (ctx == NULL) {
free_tlist (origline);
return 3;
} else {
p = tline->text+1;
p += strspn(p, "$");
smhead = &ctx->localmac;
}
}
last = tline;
tline = tline->next;
last->next = NULL;
tline = expand_smacro (tline);
t = tline;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
free_tlist (tline);
if (!evalresult) {
free_tlist (origline);
return 3;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -