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

📄 preproc.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	else if (t->text)	{	    len += strlen(t->text);	}    }    p = line = nasm_malloc(len + 1);    for (t = tlist; t; t = t->next)    {	if (t->type == TOK_WHITESPACE)	{	    *p = ' ';		p++;		*p = '\0';	}	else if (t->text)	{	    strcpy(p, t->text);	    p += strlen(p);	}    }    *p = '\0';    return line;}/* * A scanner, suitable for use by the expression evaluator, which * operates on a line of Tokens. Expects a pointer to a pointer to * the first token in the line to be passed in as its private_data * field. */static intppscan(void *private_data, struct tokenval *tokval){    Token **tlineptr = private_data;    Token *tline;    do    {	tline = *tlineptr;	*tlineptr = tline ? tline->next : NULL;    }    while (tline && (tline->type == TOK_WHITESPACE ||		    tline->type == TOK_COMMENT));    if (!tline)	return tokval->t_type = TOKEN_EOS;    if (tline->text[0] == '$' && !tline->text[1])	return tokval->t_type = TOKEN_HERE;    if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])	return tokval->t_type = TOKEN_BASE;    if (tline->type == TOK_ID)    {	tokval->t_charptr = tline->text;	if (tline->text[0] == '$')	{	    tokval->t_charptr++;	    return tokval->t_type = TOKEN_ID;	}	/*	 * This is the only special case we actually need to worry	 * about in this restricted context.	 */	if (!nasm_stricmp(tline->text, "seg"))	    return tokval->t_type = TOKEN_SEG;	return tokval->t_type = TOKEN_ID;    }    if (tline->type == TOK_NUMBER)    {	int rn_error;	tokval->t_integer = readnum(tline->text, &rn_error);	if (rn_error)	    return tokval->t_type = TOKEN_ERRNUM;	tokval->t_charptr = NULL;	return tokval->t_type = TOKEN_NUM;    }    if (tline->type == TOK_STRING)    {	int rn_warn;	char q, *r;	int l;	r = tline->text;	q = *r++;	l = strlen(r);	if (l == 0 || r[l - 1] != q)	    return tokval->t_type = TOKEN_ERRNUM;	tokval->t_integer = readstrnum(r, l - 1, &rn_warn);	if (rn_warn)	    error(ERR_WARNING | ERR_PASS1, "character constant too long");	tokval->t_charptr = NULL;	return tokval->t_type = TOKEN_NUM;    }    if (tline->type == TOK_OTHER)    {	if (!strcmp(tline->text, "<<"))	    return tokval->t_type = TOKEN_SHL;	if (!strcmp(tline->text, ">>"))	    return tokval->t_type = TOKEN_SHR;	if (!strcmp(tline->text, "//"))	    return tokval->t_type = TOKEN_SDIV;	if (!strcmp(tline->text, "%%"))	    return tokval->t_type = TOKEN_SMOD;	if (!strcmp(tline->text, "=="))	    return tokval->t_type = TOKEN_EQ;	if (!strcmp(tline->text, "<>"))	    return tokval->t_type = TOKEN_NE;	if (!strcmp(tline->text, "!="))	    return tokval->t_type = TOKEN_NE;	if (!strcmp(tline->text, "<="))	    return tokval->t_type = TOKEN_LE;	if (!strcmp(tline->text, ">="))	    return tokval->t_type = TOKEN_GE;	if (!strcmp(tline->text, "&&"))	    return tokval->t_type = TOKEN_DBL_AND;	if (!strcmp(tline->text, "^^"))	    return tokval->t_type = TOKEN_DBL_XOR;	if (!strcmp(tline->text, "||"))	    return tokval->t_type = TOKEN_DBL_OR;    }    /*     * We have no other options: just return the first character of     * the token text.     */    return tokval->t_type = tline->text[0];}/* * Compare a string to the name of an existing macro; this is a * simple wrapper which calls either strcmp or nasm_stricmp * depending on the value of the `casesense' parameter. */static intmstrcmp(char *p, char *q, int casesense){    return casesense ? strcmp(p, q) : nasm_stricmp(p, q);}/* * Return the Context structure associated with a %$ token. Return * NULL, having _already_ reported an error condition, if the * context stack isn't deep enough for the supplied number of $ * signs. * If all_contexts == TRUE, contexts that enclose current are * also scanned for such smacro, until it is found; if not - * only the context that directly results from the number of $'s * in variable's name. */static Context *get_ctx(char *name, int all_contexts){    Context *ctx;    SMacro *m;    int i;    if (!name || name[0] != '%' || name[1] != '$')	return NULL;    if (!cstk)    {	error(ERR_NONFATAL, "`%s': context stack is empty", name);	return NULL;    }    for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)    {	ctx = ctx->next;/*        i--;  Lino - 02/25/02 */    }    if (!ctx)    {	error(ERR_NONFATAL, "`%s': context stack is only"		" %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));	return NULL;    }    if (!all_contexts)	return ctx;    do    {	/* Search for this smacro in found context */	m = ctx->localmac;	while (m)	{	    if (!mstrcmp(m->name, name, m->casesense))		return ctx;	    m = m->next;	}	ctx = ctx->next;    }    while (ctx);    return NULL;}/* * Open an include file. This routine must always return a valid * file pointer if it returns - it's responsible for throwing an * ERR_FATAL and bombing out completely if not. It should also try * the include path one by one until it finds the file or reaches * the end of the path. */static FILE *inc_fopen(char *file){    FILE *fp;    char *prefix = "", *combine;    IncPath *ip = ipath;    static int namelen = 0;    int len = strlen(file);    while (1)    {	combine = nasm_malloc(strlen(prefix) + len + 1);	strcpy(combine, prefix);	strcat(combine, file);	fp = fopen(combine, "r");	if (pass == 0 && fp)	{	    namelen += strlen(combine) + 1;	    if (namelen > 62)	    {		printf(" \\\n  ");		namelen = 2;	    }	    printf(" %s", combine);	}	nasm_free(combine);	if (fp)	    return fp;	if (!ip)	    break;	prefix = ip->path;	ip = ip->next;    }    error(ERR_FATAL, "unable to open include file `%s'", file);    return NULL;		/* never reached - placate compilers */}/* * Determine if we should warn on defining a single-line macro of * name `name', with `nparam' parameters. If nparam is 0 or -1, will * return TRUE if _any_ single-line macro of that name is defined. * Otherwise, will return TRUE if a single-line macro with either * `nparam' or no parameters is defined. * * If a macro with precisely the right number of parameters is * defined, or nparam is -1, the address of the definition structure * will be returned in `defn'; otherwise NULL will be returned. If `defn' * is NULL, no action will be taken regarding its contents, and no * error will occur. * * Note that this is also called with nparam zero to resolve * `ifdef'. * * If you already know which context macro belongs to, you can pass * the context pointer as first parameter; if you won't but name begins * with %$ the context will be automatically computed. If all_contexts * is true, macro will be searched in outer contexts as well. */static intsmacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,	int nocase){    SMacro *m;    if (ctx)	m = ctx->localmac;    else if (name[0] == '%' && name[1] == '$')    {	if (cstk)	    ctx = get_ctx(name, FALSE);	if (!ctx)	    return FALSE;	/* got to return _something_ */	m = ctx->localmac;    }    else	m = smacros[hash(name)];    while (m)    {	if (!mstrcmp(m->name, name, m->casesense && nocase) &&		(nparam <= 0 || m->nparam == 0 || nparam == m->nparam))	{	    if (defn)	    {		if (nparam == m->nparam || nparam == -1)		    *defn = m;		else		    *defn = NULL;	    }	    return TRUE;	}	m = m->next;    }    return FALSE;}/* * Count and mark off the parameters in a multi-line macro call. * This is called both from within the multi-line macro expansion * code, and also to mark off the default parameters when provided * in a %macro definition line. */static voidcount_mmac_params(Token * t, int *nparam, Token *** params){    int paramsize, brace;    *nparam = paramsize = 0;    *params = NULL;    while (t)    {	if (*nparam >= paramsize)	{	    paramsize += PARAM_DELTA;	    *params = nasm_realloc(*params, sizeof(**params) * paramsize);	}	skip_white_(t);	brace = FALSE;	if (tok_is_(t, "{"))	    brace = TRUE;	(*params)[(*nparam)++] = t;	while (tok_isnt_(t, brace ? "}" : ","))	    t = t->next;	if (t)	{			/* got a comma/brace */	    t = t->next;	    if (brace)	    {		/*		 * Now we've found the closing brace, look further		 * for the comma.		 */		skip_white_(t);		if (tok_isnt_(t, ","))		{		    error(ERR_NONFATAL,			    "braces do not enclose all of macro parameter");		    while (tok_isnt_(t, ","))			t = t->next;		}		if (t)		    t = t->next;	/* eat the comma */	    }	}    }}/* * Determine whether one of the various `if' conditions is true or * not. * * We must free the tline we get passed. */static intif_condition(Token * tline, int i){    int j, casesense;    Token *t, *tt, **tptr, *origline;    struct tokenval tokval;    expr *evalresult;    origline = tline;    switch (i)    {	case PP_IFCTX:	case PP_ELIFCTX:	case PP_IFNCTX:	case PP_ELIFNCTX:	    j = FALSE;		/* have we matched yet? */	    while (cstk && tline)	    {		skip_white_(tline);		if (!tline || tline->type != TOK_ID)		{		    error(ERR_NONFATAL,			    "`%s' expects context identifiers",			    directives[i]);		    free_tlist(origline);		    return -1;		}		if (!nasm_stricmp(tline->text, cstk->name))		    j = TRUE;		tline = tline->next;	    }	    if (i == PP_IFNCTX || i == PP_ELIFNCTX)		j = !j;	    free_tlist(origline);	    return j;	case PP_IFDEF:	case PP_ELIFDEF:	case PP_IFNDEF:	case PP_ELIFNDEF:	    j = FALSE;		/* have we matched yet? */	    while (tline)	    {		skip_white_(tline);		if (!tline || (tline->type != TOK_ID &&				(tline->type != TOK_PREPROC_ID ||					tline->text[1] != '$')))		{		    error(ERR_NONFATAL,			  "`%s' expects macro identifiers",			  directives[i]);		    free_tlist(origline);		    return -1;		}		if (smacro_defined(NULL, tline->text, 0, NULL, 1))		    j = TRUE;		tline = tline->next;	    }	    if (i == PP_IFNDEF || i == PP_ELIFNDEF)		j = !j;	    free_tlist(origline);	    return j;	case PP_IFIDN:	case PP_ELIFIDN:	case PP_IFNIDN:	case PP_ELIFNIDN:	case PP_IFIDNI:	case PP_ELIFIDNI:	case PP_IFNIDNI:	case PP_ELIFNIDNI:	    tline = expand_smacro(tline);	    t = tt = tline;	    while (tok_isnt_(tt, ","))		tt = tt->next;	    if (!tt)	    {		error(ERR_NONFATAL,			"`%s' expects two comma-separated arguments",			directives[i]);		free_tlist(tline);		return -1;	    }	    tt = tt->next;	    casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||		    i == PP_IFNIDN || i == PP_ELIFNIDN);	    j = TRUE;		/* assume equality unless proved not */	    while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)	    {		if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))		{		    error(ERR_NONFATAL, "`%s': more than one comma on line",			    directives[i]);		    free_tlist(tline);		    return -1;		}		if (t->type == TOK_WHITESPACE)		{		    t = t->next;		    continue;		}		else if (tt->type == TOK_WHITESPACE)		{		    tt = tt->next;		    continue;		}		else if (tt->type != t->type ||			mstrcmp(tt->text, t->text, casesense))		{		    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,

⌨️ 快捷键说明

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