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

📄 tkcond.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
字号:
/* * tkcond.c * * Eric Youngdale was the original author of xconfig. * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer. * * This file takes the tokenized statement list and transforms 'if ...' * statements.  For each simple statement, I find all of the 'if' statements * that enclose it, and attach the aggregate conditionals of those 'if' * statements to the cond list of the simple statement. * * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net> * - Steam-clean this file.  I tested this by generating kconfig.tk for *   every architecture and comparing it character-for-character against *   the output of the old tkparse. * * 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl> * - kvariables removed; all variables are stored in a single table now * - some elimination of options non-valid for current architecture *   implemented. * - negation (!) eliminated from conditions * * TO DO: * - xconfig is at the end of its life cycle.  Contact <mec@shout.net> if *   you are interested in working on the replacement. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "tkparse.h"/* * Mark variables which are defined anywhere. */static void mark_variables( struct kconfig * scfg ){    struct kconfig * cfg;    int i;    for ( i = 1; i <= max_varnum; i++ )	vartable[i].defined = 0;    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )    {	if ( cfg->token == token_bool	||   cfg->token == token_choice_item	||   cfg->token == token_define_bool	||   cfg->token == token_define_hex	||   cfg->token == token_define_int	||   cfg->token == token_define_string	||   cfg->token == token_define_tristate	||   cfg->token == token_dep_bool	||   cfg->token == token_dep_mbool	||   cfg->token == token_dep_tristate	||   cfg->token == token_hex	||   cfg->token == token_int	||   cfg->token == token_string	||   cfg->token == token_tristate	||   cfg->token == token_unset )	{	    if ( cfg->nameindex > 0 )	/* paranoid */	    {		vartable[cfg->nameindex].defined = 1;	    }	}    }}static void free_cond( struct condition *cond ){    struct condition *tmp, *tmp1;    for ( tmp = cond; tmp; tmp = tmp1 )    {	tmp1 = tmp->next;	free( (void*)tmp );    }}/* * Remove the bang operator from a condition to avoid priority problems. * "!" has different priorities as "test" command argument and in  * a tk script. */static struct condition * remove_bang( struct condition * condition ){    struct condition * conda, * condb, * prev = NULL;    for ( conda = condition; conda; conda = conda->next )    {	if ( conda->op == op_bang && conda->next &&	   ( condb = conda->next->next ) )	{	    if ( condb->op == op_eq || condb->op == op_neq )	    {		condb->op = (condb->op == op_eq) ? op_neq : op_eq;		conda->op = op_nuked;		if ( prev )		{		    prev->next = conda->next;		}		else		{		    condition = conda->next;		}		conda->next = NULL;		free_cond( conda );		conda = condb;	    }	}	prev = conda;    }    return condition;}/* * Make a new condition chain by joining the current condition stack with * the "&&" operator for glue. */static struct condition * join_condition_stack( struct condition * conditions [],    int depth ){    struct condition * cond_list;    struct condition * cond_last;    int i, is_first = 1;    cond_list = cond_last = NULL;    for ( i = 0; i < depth; i++ )    {	if ( conditions[i]->op == op_false )	{	    struct condition * cnew;	    /* It is always false condition */	    cnew = malloc( sizeof(*cnew) );	    memset( cnew, 0, sizeof(*cnew) );	    cnew->op = op_false;	    cond_list = cond_last = cnew;	    goto join_done;	}    }    for ( i = 0; i < depth; i++ )    {	struct condition * cond;	struct condition * cnew;	int add_paren;	/* omit always true conditions */	if ( conditions[i]->op == op_true )	    continue;	/* if i have another condition, add an '&&' operator */	if ( !is_first )	{	    cnew = malloc( sizeof(*cnew) );	    memset( cnew, 0, sizeof(*cnew) );	    cnew->op = op_and;	    cond_last->next = cnew;	    cond_last = cnew;	}	if ( conditions[i]->op != op_lparen )	{	    /* add a '(' */	    add_paren = 1;	    cnew = malloc( sizeof(*cnew) );	    memset( cnew, 0, sizeof(*cnew) );	    cnew->op = op_lparen;	    if ( cond_last == NULL )		{ cond_list = cond_last = cnew; }	    else		{ cond_last->next = cnew; cond_last = cnew; }	}	else	{	    add_paren = 0;	}	/* duplicate the chain */	for ( cond = conditions [i]; cond != NULL; cond = cond->next )	{	    cnew            = malloc( sizeof(*cnew) );	    cnew->next      = NULL;	    cnew->op        = cond->op;	    cnew->str       = cond->str ? strdup( cond->str ) : NULL;	    cnew->nameindex = cond->nameindex;	    if ( cond_last == NULL )		{ cond_list = cond_last = cnew; }	    else		{ cond_last->next = cnew; cond_last = cnew; }	}	if ( add_paren )	{	    /* add a ')' */	    cnew = malloc( sizeof(*cnew) );	    memset( cnew, 0, sizeof(*cnew) );	    cnew->op = op_rparen;	    cond_last->next = cnew;	    cond_last = cnew;	}	is_first = 0;    }    /*     * Remove duplicate conditions.     */    {	struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;	for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )	{	    if ( cond1->op == op_lparen )	    {		cond1b = cond1 ->next; if ( cond1b == NULL ) break;		cond1c = cond1b->next; if ( cond1c == NULL ) break;		cond1d = cond1c->next; if ( cond1d == NULL ) break;		cond1e = cond1d->next; if ( cond1e == NULL ) break;		cond1f = cond1e->next; if ( cond1f == NULL ) break;		if ( cond1b->op == op_variable		&& ( cond1c->op == op_eq || cond1c->op == op_neq )		&&   cond1d->op == op_constant 		&&   cond1e->op == op_rparen )		{		    struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;		    for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )		    {			if ( cond2->op == op_lparen )			{			    cond2b = cond2 ->next; if ( cond2b == NULL ) break;			    cond2c = cond2b->next; if ( cond2c == NULL ) break;			    cond2d = cond2c->next; if ( cond2d == NULL ) break;			    cond2e = cond2d->next; if ( cond2e == NULL ) break;			    cond2f = cond2e->next;			    /* look for match */			    if ( cond2b->op == op_variable			    &&   cond2b->nameindex == cond1b->nameindex			    &&   cond2c->op == cond1c->op			    &&   cond2d->op == op_constant			    &&   strcmp( cond2d->str, cond1d->str ) == 0			    &&   cond2e->op == op_rparen )			    {				/* one of these must be followed by && */				if ( cond1f->op == op_and				|| ( cond2f != NULL && cond2f->op == op_and ) )				{				    /* nuke the first duplicate */				    cond1 ->op = op_nuked;				    cond1b->op = op_nuked;				    cond1c->op = op_nuked;				    cond1d->op = op_nuked;				    cond1e->op = op_nuked;				    if ( cond1f->op == op_and )					cond1f->op = op_nuked;				    else					cond2f->op = op_nuked;				}			    }			}		    }		}	    }	}    }join_done:    return cond_list;}static char * current_arch = NULL;/* * Eliminating conditions with ARCH = <not current>. */static struct condition *eliminate_other_arch( struct condition *list ){    struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;    if ( current_arch == NULL )	current_arch = getenv( "ARCH" );    if ( current_arch == NULL )    {	fprintf( stderr, "error: ARCH undefined\n" );	exit( 1 );    }    if ( cond1a->op == op_variable    && ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) )    {	cond1b = cond1a->next; if ( cond1b == NULL ) goto done;	cond1c = cond1b->next; if ( cond1c == NULL ) goto done;	cond1d = cond1c->next;	if ( cond1c->op == op_constant && cond1d == NULL )	{	    if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))	    ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for another architecture */ 		cond1a->op = op_false;		cond1a->next = NULL;		free_cond( cond1b );		return cond1a;	    }	    else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))		 ||   (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for current architecture */		cond1a->op = op_true;		cond1a->next = NULL;		free_cond( cond1b );		return cond1a;	    }	}	else if ( cond1c->op == op_constant && cond1d->op == op_or )	{	    if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))	    ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for another architecture */ 		cond1b = cond1d->next;		cond1d->next = NULL;		free_cond( cond1a );		return eliminate_other_arch( cond1b );	    }	    else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))		 || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for current architecture */		cond1a->op = op_true;		cond1a->next = NULL;		free_cond( cond1b );		return cond1a;	    }	}	else if ( cond1c->op == op_constant && cond1d->op == op_and )	{	    if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))	    ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for another architecture */		int l_par = 0;				for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next )		{		    if ( cond1c->op == op_lparen )			l_par++;		    else if ( cond1c->op == op_rparen )			l_par--;		    else if ( cond1c->op == op_or && l_par == 0 )		    /* Expression too complex - don't touch */			return cond1a;		    else if ( l_par < 0 )		    {			fprintf( stderr, "incorrect condition: programming error ?\n" );			exit( 1 );		    }		}		cond1a->op = op_false;		cond1a->next = NULL;		free_cond( cond1b );		return cond1a;	    }	    else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))		 || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )	    {		/* This is for current architecture */		cond1b = cond1d->next;		cond1d->next = NULL;		free_cond( cond1a );		return eliminate_other_arch( cond1b );	    }	}    }    if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )    {	cond1b = cond1a->next; if ( cond1b == NULL ) goto done;	cond1c = cond1b->next; if ( cond1c == NULL ) goto done;	cond1d = cond1c->next;	if ( cond1c->op == op_constant	&& ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/	{	    if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )	    {		cond1a->op = op_false;		cond1a->next = NULL;		free_cond( cond1b );		return cond1a;	    }	}	else if ( cond1c->op == op_constant && cond1d->op == op_or )	{	    if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )	    {		cond1b = cond1d->next;		cond1d->next = NULL;		free_cond( cond1a );		return eliminate_other_arch( cond1b );	    }	}    }done:    return list;}/* * This is the main transformation function. */void fix_conditionals( struct kconfig * scfg ){    struct kconfig * cfg;    /*     * Transform op_variable to op_kvariable.     */    mark_variables( scfg );    /*     * Walk the statement list, maintaining a stack of current conditions.     *   token_if      push its condition onto the stack.     *   token_else    invert the condition on the top of the stack.     *   token_endif   pop the stack.     *     * For a simple statement, create a condition chain by joining together     * all of the conditions on the stack.     */    {	struct condition * cond_stack [32];	int depth = 0;	struct kconfig * prev = NULL;	for ( cfg = scfg; cfg != NULL; cfg = cfg->next )	{	    int good = 1;	    switch ( cfg->token )	    {	    default:		break;	    case token_if:		cond_stack [depth++] =		    remove_bang( eliminate_other_arch( cfg->cond ) );		cfg->cond = NULL;		break;	    case token_else:		{		    /*		     * Invert the condition chain.		     *		     * Be careful to transfrom op_or to op_and1, not op_and.		     * I will need this later in the code that removes		     * duplicate conditions.		     */		    struct condition * cond;		    for ( cond  = cond_stack [depth-1];			  cond != NULL;			  cond  = cond->next )		    {			switch( cond->op )			{			default:     break;			case op_and: cond->op = op_or;   break;			case op_or:  cond->op = op_and1; break;			case op_neq: cond->op = op_eq;   break;			case op_eq:  cond->op = op_neq;  break;			case op_true: cond->op = op_false;break;			case op_false:cond->op = op_true; break;			}		    }		}		break;	    case token_fi:		--depth;		break;	    case token_bool:	    case token_choice_item:	    case token_choice_header:	    case token_comment:	    case token_define_bool:	    case token_define_hex:	    case token_define_int:	    case token_define_string:	    case token_define_tristate:	    case token_endmenu:	    case token_hex:	    case token_int:	    case token_mainmenu_option:	    case token_string:	    case token_tristate:	    case token_unset:		cfg->cond = join_condition_stack( cond_stack, depth );		if ( cfg->cond && cfg->cond->op == op_false )		{		    good = 0;		    if ( prev )			prev->next = cfg->next;		    else			scfg = cfg->next;		}		break;	    case token_dep_bool:	    case token_dep_mbool:	    case token_dep_tristate:		/*		 * Same as the other simple statements, plus an additional		 * condition for the dependency.		 */		if ( cfg->cond )		{		    cond_stack [depth] = eliminate_other_arch( cfg->cond );		    cfg->cond = join_condition_stack( cond_stack, depth+1 );		}		else		{		    cfg->cond = join_condition_stack( cond_stack, depth );		}		if ( cfg->cond && cfg->cond->op == op_false )		{		    good = 0;		    if ( prev )			prev->next = cfg->next;		    else			scfg = cfg->next;		}		break;	    }	    if ( good )		prev = cfg;	}    }}#if 0void dump_condition( struct condition *list ){    struct condition *tmp;    for ( tmp = list; tmp; tmp = tmp->next )    {	switch (tmp->op)	{	default:	    break;	case op_variable:	    printf( " %s", vartable[tmp->nameindex].name );	    break;	case op_constant: 	    printf( " %s", tmp->str );	    break;	case op_eq:	    printf( " =" );	    break;	case op_bang:	    printf( " !" );	    break;	case op_neq:	    printf( " !=" );	    break;	case op_and:	case op_and1:	    printf( " -a" );	    break;	case op_or:	    printf( " -o" );	    break;	case op_true:	    printf( " TRUE" );	    break;	case op_false:	    printf( " FALSE" );	    break;	case op_lparen:	    printf( " (" );	    break;	case op_rparen:	    printf( " )" );	    break;	}    }    printf( "\n" );}#endif

⌨️ 快捷键说明

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