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

📄 preproc.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 5 页
字号:
		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))		j = COND_NEVER;	    else	    {		j = if_condition(tline->next, i);		tline->next = NULL;	/* it got freed */		free_tlist(origline);		j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;	    }	    cond = nasm_malloc(sizeof(Cond));	    cond->next = istk->conds;	    cond->state = j;	    istk->conds = cond;	    return DIRECTIVE_FOUND;	case PP_ELIF:	case PP_ELIFCTX:	case PP_ELIFDEF:	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:	case PP_ELIFSTR:	    if (!istk->conds)		error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);	    if (emitting(istk->conds->state)		    || istk->conds->state == COND_NEVER)		istk->conds->state = COND_NEVER;	    else	    {		/*		 * IMPORTANT: In the case of %if, we will already have		 * called expand_mmac_params(); however, if we're		 * processing an %elif we must have been in a		 * non-emitting mode, which would have inhibited		 * the normal invocation of expand_mmac_params().  Therefore,		 * we have to do it explicitly here.		 */		 j = if_condition(expand_mmac_params(tline->next), i);		 tline->next = NULL; /* it got freed */		free_tlist(origline);		istk->conds->state =			j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;	    }	    return DIRECTIVE_FOUND;	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 DIRECTIVE_FOUND;	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 DIRECTIVE_FOUND;	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);	    tline = expand_id(tline);	    if (!tok_type_(tline, TOK_ID))	    {		error(ERR_NONFATAL,			"`%%%smacro' expects a macro name",			(i == PP_IMACRO ? "i" : ""));		return DIRECTIVE_FOUND;	    }	    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 = expand_smacro(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 DIRECTIVE_FOUND;	case PP_ENDM:	case PP_ENDMACRO:	    if (!defining)	    {		error(ERR_NONFATAL, "`%s': not defining a macro",			tline->text);		return DIRECTIVE_FOUND;	    }	    k = hash(defining->name);	    defining->next = mmacros[k];	    mmacros[k] = defining;	    defining = NULL;	    free_tlist(origline);	    return DIRECTIVE_FOUND;	case PP_ROTATE:	    if (tline->next && tline->next->type == TOK_WHITESPACE)		tline = tline->next;	    if (tline->next == NULL)	    {		free_tlist(origline);		error(ERR_NONFATAL, "`%%rotate' missing rotate count");		return DIRECTIVE_FOUND;	    }	    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 DIRECTIVE_FOUND;	    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 DIRECTIVE_FOUND;	    }	    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");	    } 	    else if (mmac->nparam == 0)	    {		error(ERR_NONFATAL,			"`%%rotate' invoked within macro without parameters");	    }	    else	    {		mmac->rotate = mmac->rotate + reloc_value(evalresult);				if (mmac->rotate < 0)		    mmac->rotate = 			mmac->nparam - (-mmac->rotate) % mmac->nparam;		mmac->rotate %= mmac->nparam;	    }	    return DIRECTIVE_FOUND;	case PP_REP:	    nolist = FALSE;	    do {		tline = tline->next;	    } while (tok_type_(tline, TOK_WHITESPACE));	    if (tok_type_(tline, TOK_ID) &&		nasm_stricmp(tline->text, ".nolist") == 0)	    {		nolist = TRUE;		do {		    tline = tline->next;		} while (tok_type_(tline, TOK_WHITESPACE));	    }	    if (tline)	    {		t = expand_smacro(tline);		tptr = &t;		tokval.t_type = TOKEN_INVALID;		evalresult =		    evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);		if (!evalresult)		{		    free_tlist(origline);		    return DIRECTIVE_FOUND;		}		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 DIRECTIVE_FOUND;		}		i = (int)reloc_value(evalresult) + 1;	    }	    else	    {		error(ERR_NONFATAL, "`%%rep' expects a repeat count");		i = 0;	    }	    free_tlist(origline);	    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 = i;	    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 DIRECTIVE_FOUND;	case PP_ENDREP:	    if (!defining || defining->name)	    {		error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");		return DIRECTIVE_FOUND;	    }	    /*	     * 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 DIRECTIVE_FOUND;	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 DIRECTIVE_FOUND;	case PP_XDEFINE:	case PP_IXDEFINE:	case PP_DEFINE:	case PP_IDEFINE:	    tline = tline->next;	    skip_white_(tline);	    tline = expand_id(tline);	    if (!tline || (tline->type != TOK_ID &&			    (tline->type != TOK_PREPROC_ID ||				    tline->text[1] != '$')))	    {		error(ERR_NONFATAL,			"`%%%s%sdefine' expects a macro identifier",			((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),			((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));		free_tlist(origline);		return DIRECTIVE_FOUND;	    }	    ctx = get_ctx(tline->text, FALSE);	    if (!ctx)		smhead = &smacros[hash(tline->text)];	    else		smhead = &ctx->localmac;	    mname = tline->text;	    last = tline;	    param_start = tline = tline->next;	    nparam = 0;	    /* Expand the macro definition now for %xdefine and %ixdefine */	    if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))		tline = expand_smacro(tline);	    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 DIRECTIVE_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -