summaryrefslogtreecommitdiff
path: root/preproc.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-05-07 00:10:05 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-05-07 00:10:05 +0000
commit6574726f2164d7d61f2b23e3fecaaf452294ceda (patch)
treeeb7a4edd8d6738262c96e221855e6e1dcb6d138a /preproc.c
parent290b514fac0490d12f692183b876a6c519941797 (diff)
downloadnasm-6574726f2164d7d61f2b23e3fecaaf452294ceda.tar.gz
nasm-6574726f2164d7d61f2b23e3fecaaf452294ceda.tar.bz2
nasm-6574726f2164d7d61f2b23e3fecaaf452294ceda.zip
Add %ifmacro and friends, and fix two minor bugs:
a) The argument to %elif* is handled different than the one to %if* b) Incorrect error messages for the %ifdef variants
Diffstat (limited to 'preproc.c')
-rw-r--r--preproc.c143
1 files changed, 116 insertions, 27 deletions
diff --git a/preproc.c b/preproc.c
index 6c7106d..cba80e9 100644
--- a/preproc.c
+++ b/preproc.c
@@ -1,3 +1,4 @@
+/* -*- mode: c; c-file-style: "bsd" -*- */
/* preproc.c macro preprocessor for the Netwide Assembler
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
@@ -276,12 +277,12 @@ static int inverse_ccs[] = {
static char *directives[] = {
"%arg",
"%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
- "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
- "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
+ "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
+ "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
"%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
"%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
- "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
- "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
+ "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx",
+ "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
"%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
"%ixdefine", "%line",
"%local",
@@ -293,12 +294,12 @@ enum
{
PP_ARG,
PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
- PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
- PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
+ PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
+ PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
- PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
- PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
+ PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX,
+ PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
PP_IXDEFINE, PP_LINE,
PP_LOCAL,
@@ -307,6 +308,12 @@ enum
PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
};
+/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
+static int is_condition(int arg)
+{
+ return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) ||
+ ((arg >= PP_IF) && (arg <= PP_IFSTR));
+}
/* For TASM compatibility we need to be able to recognise TASM compatible
* conditional compilation directives. Using the NASM pre-processor does
@@ -1471,8 +1478,8 @@ if_condition(Token * tline, int i)
tline->text[1] != '$')))
{
error(ERR_NONFATAL,
- "`%%if%sdef' expects macro identifiers",
- (i == PP_ELIFNDEF ? "n" : ""));
+ "`%s' expects macro identifiers",
+ directives[i]);
free_tlist(origline);
return -1;
}
@@ -1549,6 +1556,98 @@ if_condition(Token * tline, int i)
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:
@@ -1704,22 +1803,8 @@ do_directive(Token * tline)
* directives.
*/
if (((istk->conds && !emitting(istk->conds->state)) ||
- (istk->mstk && !istk->mstk->in_progress)) &&
- i != PP_IF && i != PP_ELIF &&
- i != PP_IFCTX && i != PP_ELIFCTX &&
- i != PP_IFDEF && i != PP_ELIFDEF &&
- i != PP_IFID && i != PP_ELIFID &&
- i != PP_IFIDN && i != PP_ELIFIDN &&
- i != PP_IFIDNI && i != PP_ELIFIDNI &&
- i != PP_IFNCTX && i != PP_ELIFNCTX &&
- i != PP_IFNDEF && i != PP_ELIFNDEF &&
- i != PP_IFNID && i != PP_ELIFNID &&
- i != PP_IFNIDN && i != PP_ELIFNIDN &&
- i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
- i != PP_IFNNUM && i != PP_ELIFNNUM &&
- i != PP_IFNSTR && i != PP_ELIFNSTR &&
- i != PP_IFNUM && i != PP_ELIFNUM &&
- i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF)
+ (istk->mstk && !istk->mstk->in_progress)) &&
+ !is_condition(i))
{
return 0;
}
@@ -2135,11 +2220,13 @@ do_directive(Token * tline)
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:
@@ -2165,11 +2252,13 @@ do_directive(Token * tline)
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:
@@ -2181,7 +2270,7 @@ do_directive(Token * tline)
istk->conds->state = COND_NEVER;
else
{
- j = if_condition(expand_mmac_params(tline->next), i);
+ j = if_condition(tline->next, i);
tline->next = NULL; /* it got freed */
free_tlist(origline);
istk->conds->state =