📄 preproc.c
字号:
j = FALSE; /* found mismatching tokens */
break;
}
else
{
t = t->next;
tt = tt->next;
continue;
}
}
if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
j = FALSE; /* trailing gunk on one end or other */
if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
i == PP_IFNIDNI || i == PP_ELIFNIDNI)
j = !j;
free_tlist(tline);
return j;
case PP_IFMACRO:
case PP_ELIFMACRO:
case PP_IFNMACRO:
case PP_ELIFNMACRO:
{
int found = 0;
MMacro searching, *mmac;
tline = tline->next;
skip_white_(tline);
tline = expand_id(tline);
if (!tok_type_(tline, TOK_ID))
{
error(ERR_NONFATAL,
"`%s' expects a macro name",
directives[i]);
return -1;
}
searching.name = nasm_strdup(tline->text);
searching.casesense = (i == PP_MACRO);
searching.plus = FALSE;
searching.nolist = FALSE;
searching.in_progress = FALSE;
searching.rep_nest = NULL;
searching.nparam_min = 0;
searching.nparam_max = INT_MAX;
tline = expand_smacro(tline->next);
skip_white_(tline);
if (!tline)
{
} else if (!tok_type_(tline, TOK_NUMBER))
{
error(ERR_NONFATAL,
"`%s' expects a parameter count or nothing",
directives[i]);
}
else
{
searching.nparam_min = searching.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, "*"))
searching.nparam_max = INT_MAX;
else if (!tok_type_(tline, TOK_NUMBER))
error(ERR_NONFATAL,
"`%s' expects a parameter count after `-'",
directives[i]);
else
{
searching.nparam_max = readnum(tline->text, &j);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
tline->text);
if (searching.nparam_min > searching.nparam_max)
error(ERR_NONFATAL,
"minimum parameter count exceeds maximum");
}
}
if (tline && tok_is_(tline->next, "+"))
{
tline = tline->next;
searching.plus = TRUE;
}
mmac = mmacros[hash(searching.name)];
while (mmac)
{
if (!strcmp(mmac->name, searching.name) &&
(mmac->nparam_min <= searching.nparam_max
|| searching.plus)
&& (searching.nparam_min <= mmac->nparam_max
|| mmac->plus))
{
found = TRUE;
break;
}
mmac = mmac->next;
}
nasm_free(searching.name);
free_tlist(origline);
if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
found = !found;
return found;
}
case PP_IFID:
case PP_ELIFID:
case PP_IFNID:
case PP_ELIFNID:
case PP_IFNUM:
case PP_ELIFNUM:
case PP_IFNNUM:
case PP_ELIFNNUM:
case PP_IFSTR:
case PP_ELIFSTR:
case PP_IFNSTR:
case PP_ELIFNSTR:
tline = expand_smacro(tline);
t = tline;
while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
j = FALSE; /* placate optimiser */
if (t)
switch (i)
{
case PP_IFID:
case PP_ELIFID:
case PP_IFNID:
case PP_ELIFNID:
j = (t->type == TOK_ID);
break;
case PP_IFNUM:
case PP_ELIFNUM:
case PP_IFNNUM:
case PP_ELIFNNUM:
j = (t->type == TOK_NUMBER);
break;
case PP_IFSTR:
case PP_ELIFSTR:
case PP_IFNSTR:
case PP_ELIFNSTR:
j = (t->type == TOK_STRING);
break;
}
if (i == PP_IFNID || i == PP_ELIFNID ||
i == PP_IFNNUM || i == PP_ELIFNNUM ||
i == PP_IFNSTR || i == PP_ELIFNSTR)
j = !j;
free_tlist(tline);
return j;
case PP_IF:
case PP_ELIF:
t = tline = expand_smacro(tline);
tptr = &t;
tokval.t_type = TOKEN_INVALID;
evalresult = evaluate(ppscan, tptr, &tokval,
NULL, pass | CRITICAL, error, NULL);
free_tlist(tline);
if (!evalresult)
return -1;
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
if (!is_simple(evalresult))
{
error(ERR_NONFATAL,
"non-constant value given to `%s'", directives[i]);
return -1;
}
return reloc_value(evalresult) != 0;
default:
error(ERR_FATAL,
"preprocessor directive `%s' not yet implemented",
directives[i]);
free_tlist(origline);
return -1; /* yeah, right */
}
}
/*
* Expand macros in a string. Used in %error and %include directives.
* First tokenise the string, apply "expand_smacro" and then de-tokenise back.
* The returned variable should ALWAYS be freed after usage.
*/
void
expand_macros_in_string(char **p)
{
Token *line = tokenise(*p);
line = expand_smacro(line);
*p = detoken(line, FALSE);
}
/**
* find and process preprocessor directive in passed line
* Find out if a line contains a preprocessor directive, and deal
* with it if so.
*
* If a directive _is_ found, it is the responsibility of this routine
* (and not the caller) to free_tlist() the line.
*
* @param tline a pointer to the current tokeninzed line linked list
* @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
*
*/
static int
do_directive(Token * tline)
{
int i, j, k, m, nparam, nolist;
int offset;
char *p, *mname;
Include *inc;
Context *ctx;
Cond *cond;
SMacro *smac, **smhead;
MMacro *mmac;
Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
Line *l;
struct tokenval tokval;
expr *evalresult;
MMacro *tmp_defining; /* Used when manipulating rep_nest */
origline = tline;
skip_white_(tline);
if (!tok_type_(tline, TOK_PREPROC_ID) ||
(tline->text[1] == '%' || tline->text[1] == '$'
|| tline->text[1] == '!'))
return NO_DIRECTIVE_FOUND;
i = -1;
j = elements(directives);
while (j - i > 1)
{
k = (j + i) / 2;
m = nasm_stricmp(tline->text, directives[k]);
if (m == 0) {
if (tasm_compatible_mode) {
i = k;
j = -2;
} else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
i = k;
j = -2;
}
break;
}
else if (m < 0) {
j = k;
}
else
i = k;
}
/*
* If we're in a non-emitting branch of a condition construct,
* or walking to the end of an already terminated %rep block,
* we should ignore all directives except for condition
* directives.
*/
if (((istk->conds && !emitting(istk->conds->state)) ||
(istk->mstk && !istk->mstk->in_progress)) &&
!is_condition(i))
{
return NO_DIRECTIVE_FOUND;
}
/*
* If we're defining a macro or reading a %rep block, we should
* ignore all directives except for %macro/%imacro (which
* generate an error), %endm/%endmacro, and (only if we're in a
* %rep block) %endrep. If we're in a %rep block, another %rep
* causes an error, so should be let through.
*/
if (defining && i != PP_MACRO && i != PP_IMACRO &&
i != PP_ENDMACRO && i != PP_ENDM &&
(defining->name || (i != PP_ENDREP && i != PP_REP)))
{
return NO_DIRECTIVE_FOUND;
}
if (j != -2)
{
error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
tline->text);
return NO_DIRECTIVE_FOUND; /* didn't get it */
}
switch (i)
{
case PP_STACKSIZE:
/* Directive to tell NASM what the default stack size is. The
* default is for a 16-bit stack, and this can be overriden with
* %stacksize large.
* the following form:
*
* ARG arg1:WORD, arg2:DWORD, arg4:QWORD
*/
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID)
{
error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
if (nasm_stricmp(tline->text, "flat") == 0)
{
/* All subsequent ARG directives are for a 32-bit stack */
StackSize = 4;
StackPointer = "ebp";
ArgOffset = 8;
LocalOffset = 4;
}
else if (nasm_stricmp(tline->text, "large") == 0)
{
/* All subsequent ARG directives are for a 16-bit stack,
* far function call.
*/
StackSize = 2;
StackPointer = "bp";
ArgOffset = 4;
LocalOffset = 2;
}
else if (nasm_stricmp(tline->text, "small") == 0)
{
/* All subsequent ARG directives are for a 16-bit stack,
* far function call. We don't support near functions.
*/
StackSize = 2;
StackPointer = "bp";
ArgOffset = 6;
LocalOffset = 2;
}
else
{
error(ERR_NONFATAL, "`%%stacksize' invalid size type");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
free_tlist(origline);
return DIRECTIVE_FOUND;
case PP_ARG:
/* TASM like ARG directive to define arguments to functions, in
* the following form:
*
* ARG arg1:WORD, arg2:DWORD, arg4:QWORD
*/
offset = ArgOffset;
do
{
char *arg, directive[256];
int size = StackSize;
/* Find the argument name */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID)
{
error(ERR_NONFATAL, "`%%arg' missing argument parameter");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
arg = tline->text;
/* Find the argument size type */
tline = tline->next;
if (!tline || tline->type != TOK_OTHER
|| tline->text[0] != ':')
{
error(ERR_NONFATAL,
"Syntax error processing `%%arg' directive");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
tline = tline->next;
if (!tline || tline->type != TOK_ID)
{
error(ERR_NONFATAL,
"`%%arg' missing size type parameter");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
/* Allow macro expansion of type parameter */
tt = tokenise(tline->text);
tt = expand_smacro(tt);
if (nasm_stricmp(tt->text, "byte") == 0)
{
size = MAX(StackSize, 1);
}
else if (nasm_stricmp(tt->text, "word") == 0)
{
size = MAX(StackSize, 2);
}
else if (nasm_stricmp(tt->text, "dword") == 0)
{
size = MAX(StackSize, 4);
}
else if (nasm_stricmp(tt->text, "qword") == 0)
{
size = MAX(StackSize, 8);
}
else if (nasm_stricmp(tt->text, "tword") == 0)
{
size = MAX(StackSize, 10);
}
else
{
error(ERR_NONFATAL,
"Invalid size type for `%%arg' 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)", arg, StackPointer,
offset);
do_directive(tokenise(directive));
offset += size;
/* 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_LOCAL:
/* TASM like LOCAL directive to define local variables for a
* function, in the following form:
*
* LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
*
* The '= LocalSize' at the end is ignored by NASM, but is
* required by TASM to define the local parameter size (and used
* by the TASM macro package).
*/
offset = LocalOffset;
do
{
char *local, directive[256];
int size = StackSize;
/* Find the argument name */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID)
{
error(ERR_NONFATAL,
"`%%local' missing argument parameter");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
local = tline->text;
/* Find the argument size type */
tline = tline->next;
if (!tline || tline->type != TOK_OTHER
|| tline->text[0] != ':')
{
error(ERR_NONFATAL,
"Syntax error processing `%%local' directive");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
tline = tline->next;
if (!tline || tline->type != TOK_ID)
{
error(ERR_NONFATAL,
"`%%local' missing size type parameter");
free_tlist(origline);
return DIRECTIVE_FOUND;
}
/* Allow macro expansion of type parameter */
tt = tokenise(tline->text);
tt = expand_smacro(tt);
if (nasm_stricmp(tt->text, "byte") == 0)
{
size = MAX(StackSize, 1);
}
else if (nasm_stricmp(tt->text, "word") == 0)
{
size = MAX(StackSize, 2);
}
else if (nasm_stricmp(tt->text, "dword") == 0)
{
size = MAX(StackSize, 4);
}
else if (nasm_stricmp(tt->text, "qword") == 0)
{
size = MAX(StackSize, 8);
}
else if (nasm_stricmp(tt->text, "tword") == 0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -