📄 preproc.c
字号:
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 */
snprintf(directive, sizeof(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) {
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 */
snprintf(directive, sizeof(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 */
snprintf(directive, sizeof(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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -