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

📄 macro.c

📁 主要用于大规模的测试生成方法
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************The function 'macro()' is repeatedly called by the parser to obtainits next input token. The default behaviour is just grabbing such a tokenfrom the lexical analyser.However if the fetched token is an aliased keyword, unaliasing is done.if the fetched token leads a macro call: - it will read the entire macro call in a local parse tree. - it will perform a macro expansion - subsequently deliver tokens from this expansion, until it is exhausted.   Thus the parser can perform real grammar checking on the expanded result.Note that macro calls can nest!*****************************************************************************/#include <stdio.h>#include "defines.h"#include "types.h"#include "keywords.h"/** IMPORTED ***/extern int yy_create_edf_lex();extern int yy_create_edf_lineno;extern int err_count;extern int debug;extern char yy_create_edf_text[];extern char *str_hash(), *treetxt();extern PARSETREE *get_parsetree(), *put_parsetree();extern PARSETREE *locate();extern char *keywords[];/*** EXPORTED ***/PARSETREE *token;int keywordlevelused;/*** LOCAL ***/static PARSETREE *newkeydef[MAXKEYWORDS];/* defined keywords*/static int newkeyalias[MAXKEYWORDS];	/* keyword aliases */static int curr_macro;			/* type number of macro now expanded*/static char *formal_asgn;		/* formal argument being assigned*/static int mlines[2];			/* begin-end line numbers of call*//*** FORWARD ***/extern char *lineno(), *tokentxt();extern PARSETREE *readmacrocall(), *expandmacro(), *assignformal();extern PARSETREE *buildmacro(), *cpy_parsetree(), *find_actual();int macro(){	static PARSETREE *mstack[MAXDEPTH];	/* pointers in macro storage */	static int stackp;			/* for sequential output */	static int lastline;	int type;	PARSETREE **p, *exp;again:	/* Nothing on stack from last macro expansion? */	/* then read new input from file */	if (stackp==0 && !mstack[0])	{		if (!token) token = get_parsetree();		else token->next = NULL; /* thus actually always NULL */		token->type = type = yy_create_edf_lex();		token->line = yy_create_edf_lineno;		DEBUG(9) "macro: reading token '%s' from yy_create_edf_lex (line %d)\n",			yy_create_edf_text, yy_create_edf_lineno);		switch( type)		{ case NUMBER: token->data.ival = atoi( yy_create_edf_text);		  Case STRING:		  case IDENT:  token->data.token = str_hash( yy_create_edf_text);		  Case KEYWORD: token->data.tree = NULL;			token->type = type = key_hash( yy_create_edf_text, 0);		}		/* Have I got a newly-introduced keyword name? */		/* If it was a simple keyword alias, then replace */		if (type>NKEYWORDS && newkeyalias[ type])		{	type = newkeyalias[type];			DEBUG(3) "macro: keyword alias '%s' to '%s'\n",				yy_create_edf_text, keywords[type]);		}		if (type <= NKEYWORDS) return( type);		/* Return standard EDIF item */ 		/* type is macro call requiring expansion.... */		/* save line numbers, read full macro call */		mlines[0] = yy_create_edf_lineno;		mstack[ stackp=0 ] = readmacrocall( type);		mlines[1] = lastline = yy_create_edf_lineno;	}	/****** read next token from stored macro expansion ***/	/****** if keyword alias, then unalias ****************/	/****** if macro call, then replace by its expansion **/	/** remove token from storage just before it is returned */	/** only (keyword is removed after ) ******************/	if (token) put_parsetree(token);	token = mstack[ stackp];	DEBUG(8) "macro: reading token '%s' from macro expansion stack, level %d\n",		treetxt(token), stackp);	if (!token) /* end  of list reached */	{		DEBUG(5) "macro expansion returns ')'\n");		if (stackp<=0)		{	fprintf( stderr, "Program error: end of macro stack!\n");			terminate(3);		}		stackp--;		/* all done? then clear inputline info */		if (stackp==0 && !mstack[ 0])			mlines[0] = mlines[1] = 0;		if (!token) token = get_parsetree();		else token->next = NULL;		token->line = lastline;		return( token->type = ENDLIST);	} /*  else .... */			type = token->type;	if (ISKEYWORD(type) || type==KEYWORD)	{		if (type>NKEYWORDS && newkeyalias[type])		{	DEBUG(3) "macro: keyword alias '%s' to '%s'\n",				keywords[type], keywords[newkeyalias[type]]);			token->type = type = newkeyalias[type];		}				if (type>NKEYWORDS && newkeydef[type])		{	/* macro call: replace by its expansion */			/* preform macro expansion, result in exp */			exp = expandmacro( token);			/* remove macro call from stack */			mstack[ stackp] = put_parsetree(token);			token = NULL;			if (exp)			{	/* insert nonemtpy (list?) result in stack */				DEBUG(5) "macro: insert macro-expansion in stack[%d]\n",					stackp);				for (p= &(exp->next); *p; p= &((*p)->next));				*p = mstack[ stackp];				mstack[ stackp] = exp;			} else	DEBUG(5) "macro: expansion had empty result\n");			if (stackp==0 && !mstack[0])				mlines[0] = mlines[1] = 0;			DEBUG(6) "macro: go back, try to return token to parser\n");			goto again;		}		/* reference to standard EDIF keyword */		/* remove keyword token from stack, add 'next' and 'data.tree'*/		mstack[ stackp] = token->next; /* == mstack[stackp]->next */		mstack[ ++stackp] = token->data.tree;	} else	mstack[ stackp] = token->next;	token->next = NULL;	DEBUG(5) "macro expansion returns '%s'\n", tokentxt());	lastline = token->line;	return( type);}void keywordalias( p)PARSETREE *p;{	int type, newtype;	if (keywordlevelused < 1) keywordlevelused = 1;	newtype = key_hash( p->data.tree->data.token, 1);	if (!newtype)	{	fprintf( stderr,		   "%s keywordAlias redefines existing keyword '%s'!\n",		   lineno(), p->data.tree->data.token);		err_count++;		return;	}	type = key_hash( p->data.tree->next->data.token, 0);	if (!ISKEYWORD(type))	{	fprintf( stderr,		   "%s keywordAlias references unknown keyword '%s'!\n",		   lineno(), p->data.tree->next->data.token);		err_count++;		return;	}	if (newkeyalias[type]) /* resolve multilevel alias */		type = newkeyalias[type];	newkeyalias[ newtype] = type;}void keyworddefine( p)PARSETREE *p;{	int newtype;	if (keywordlevelused < 2) keywordlevelused = 2;	newtype = key_hash( p->data.tree->data.token, 1);	if (!newtype)	{	fprintf( stderr,		   "%s keywordDefine redefines existing keyword '%s'!\n",		   lineno(), p->data.tree->data.token);		err_count++;		return;	}	newkeydef[ newtype] = p;}static PARSETREE *readmacrocall( type)int type;{	PARSETREE *call, **p;	call = get_parsetree();	call->type = (newkeyalias[type])? newkeyalias[type] : type;	call->line = yy_create_edf_lineno;	DEBUG(3) "macro: storing call '(%s'\n", keywords[call->type]);	p = &(call->data.tree);	while ((type=yy_create_edf_lex()) != ENDLIST && type != ENDFILE)	{			if (type == KEYWORD)			*p = readmacrocall( key_hash( yy_create_edf_text, 0));		else		{	*p = get_parsetree();			(*p)->type = type;			(*p)->line = yy_create_edf_lineno;			if (type == IDENT || type == STRING)				(*p)->data.token = str_hash( yy_create_edf_text);			else if (type == NUMBER)				(*p)->data.ival = atoi( yy_create_edf_text);		}		p = &((*p)->next);	}	return( call);}/**** generate new parsetree with the expansion of the macro call ***/static PARSETREE *expandmacro( call)PARSETREE *call;{	PARSETREE *formal, *mdef, *result, *args;	DEBUG(3) "macro: perform macro expansion of '%s' call (line %d)\n",		keywords[call->type], call->line);	curr_macro = call->type;	/*** get formal par decl ***/	formal = locate( newkeydef[curr_macro],		KkeywordParameters, Kformal, 0);	/*** assign formal arguments ***/	args = assignformal( formal, call->data.tree);	/*** get body of macro definition ***/	mdef = locate( newkeydef[curr_macro], Kgenerate, 0)->data.tree;	/*** building expanded result **/	result = buildmacro( args, mdef);	/*** free argument values, and return result ***/	while (args) args=put_parsetree(args);	return( result);}static PARSETREE *assignformal( formal, call)PARSETREE *formal, *call;{	PARSETREE *f, *result, **rp, *coll, *opt, **vp;	int ncolls, nopts, cnt, formal_type;;	cnt=ncolls=nopts=formal_type=0;	/* scan once for the characteristics of the declared formal args */	for (f=formal; f; f=f->next)	{	cnt++; /* count the number of declared arguments */		if (coll=locate( f, Kcollector, 0))		{	ncolls++; /* collector found */			if (!formal_type) formal_type = coll->type;		}		if (opt=locate( f, Koptional, 0))		{	nopts++; /* optional arg found */			if (!formal_type) formal_type = opt->type;		}

⌨️ 快捷键说明

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