⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preproc.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 5 页
字号:
		    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 + -