But as:
1. ARCH = ... conditions are already almost not used; CONFIG_ARCH_* = ...
are preferred now,
2. potential 2.5/CML2 backport to 2.4 is still far,
3. some architecture specyfic configs have been merged into the main tree
last time
I think this code may be usefull for novices. Please test.
The effect of this patch against 2.4.7 is shown in the table below.
ARCH --- eliminated ------ total
new old difference options
alpha 74 54 20 1443
arm 60 36 24 1476
cris 125 117 8 1454
i386 61 48 13 1514
ia64 97 52 45 1432
m68k 19 10 9 708
mips 70 50 20 1523
mips64 72 52 20 1479
parisc 24 24 0 893
ppc 80 35 45 1537
s390 0 0 0 283
s390x 0 0 0 284
sh 77 53 24 1174
sparc 30 19 11 697
sparc64 76 37 39 1044
Andrzej
*******************************************************************
diff -ur scripts.old/tkcond.c scripts/tkcond.c
--- scripts.old/tkcond.c Sat Jul 28 23:00:57 2001
+++ scripts/tkcond.c Sat Jul 28 22:58:00 2001
@@ -20,6 +20,9 @@
* implemented.
* - negation (!) eliminated from conditions
*
+ * 25 July 2001, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
+ * - eliminating some (parts of) conditions with values known at parse time
+ *
* TO DO:
* - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
* you are interested in working on the replacement.
@@ -281,14 +284,31 @@
+static int ynm_strcmp( const char *s1, const char *s2)
+{
+ if ( !strcmp( s2, "CONSTANT_N") )
+ return strcmp( s1, "n" ) && strcmp( s1, "N" );
+ else if ( !strcmp( s2, "CONSTANT_M") )
+ return strcmp( s1, "m" ) && strcmp( s1, "M" );
+ else if ( !strcmp( s2, "CONSTANT_Y") )
+ return strcmp( s1, "y" ) && strcmp( s1, "Y" );
+ else if ( !strcmp( s2, "CONSTANT_E") )
+ return strcmp( s1, "" );
+ else
+ return strcmp( s1, s2 );
+}
+
+
+
static char * current_arch = NULL;
/*
- * Eliminating conditions with ARCH = <not current>.
+ * Eliminating parts of conditions with ARCH = <not current>
+ * and CONFIG_DEFINED_VAR = <value_other_than_defined>.
*/
-static struct condition *eliminate_other_arch( struct condition *list )
+static struct condition *parse_eliminate_part( struct condition *list )
{
- struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;
+ struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL;
if ( current_arch == NULL )
current_arch = getenv( "ARCH" );
if ( current_arch == NULL )
@@ -301,117 +321,341 @@
{
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 ( cond1c->op == op_constant )
{
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;
- }
+ cond1c->op = op_false;
else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
- || (cond1b->op == op_eq && ! 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;
+ cond1c->op = op_true;
+ if ( cond1b->op == op_eq || cond1b->op == op_neq )
+ {
+ cond1c->str = NULL;
+ cond1b->next = NULL;
+ free_cond( cond1a );
+ return cond1c;
}
}
- else if ( cond1c->op == op_constant && cond1d->op == op_or )
+ }
+ else 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;
+ if ( cond1c->op == op_constant )
{
- if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
- || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
+ if ( (cond1b->op == op_eq && strcmp( cond1c->str, "" ))
+ || (cond1b->op == op_neq && ! strcmp( cond1c->str, "" )) )
+ cond1c->op = op_false;
+ else if ( (cond1b->op == op_neq && strcmp( cond1c->str, "" ))
+ || (cond1b->op == op_eq && ! strcmp( cond1c->str, "" )) )
+ cond1c->op = op_true;
+ if ( cond1b->op == op_eq || cond1b->op == op_neq )
{
- /* This is for another architecture */
- cond1b = cond1d->next;
- cond1d->next = NULL;
+ cond1c->str = NULL;
+ cond1b->next = NULL;
free_cond( cond1a );
- return eliminate_other_arch( cond1b );
+ return cond1c;
}
- else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
- || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
+ }
+ }
+ else if ( cond1a->op == op_variable
+ && vartable[cond1a->nameindex].constant == 1 )
+ {
+ cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
+ cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
+ if ( cond1c->op == op_constant )
+ {
+ if ( (cond1b->op == op_eq
+ && ynm_strcmp( cond1c->str, vartable[cond1a->nameindex].value ))
+ || (cond1b->op == op_neq
+ && ! ynm_strcmp( cond1c->str, vartable[cond1a->nameindex].value )) )
+ /* This is for another value than the defined for this variable */
+ cond1c->op = op_false;
+ else if ( (cond1b->op == op_neq
+ && ynm_strcmp( cond1c->str, vartable[cond1a->nameindex].value ))
+ || (cond1b->op == op_eq
+ && ! ynm_strcmp( cond1c->str, vartable[cond1a->nameindex].value )) )
+ /* This is for the defined value of this variable; can be omitted */
+ cond1c->op = op_true;
+ if ( cond1b->op == op_eq || cond1b->op == op_neq )
{
- /* This is for current architecture */
- cond1a->op = op_true;
- cond1a->next = NULL;
- free_cond( cond1b );
- return cond1a;
+ cond1c->str = NULL;
+ cond1b->next = NULL;
+ free_cond( cond1a );
+ return cond1c;
}
}
- else if ( cond1c->op == op_constant && cond1d->op == op_and )
+ }
+done:
+ return list;
+}
+
+
+
+/*
+ * Extracting an expresion from condition; returns its last element.
+ */
+static struct condition *xtract_expr( struct condition *list )
+{
+ struct condition *conda, *condb;
+
+ if ( list->op == op_true || list->op == op_false )
+ {
+ condb = list;
+ return condb;
+ }
+ else
+ {
+ conda = list->next; if ( ! conda ) return list;
+ condb = conda->next; if ( ! condb ) return list;
+ if ( list->op == op_variable
+ && ( conda->op == op_eq || conda->op == op_neq )
+ && ( condb->op == op_constant || condb->op == op_variable ) )
{
- if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
- || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
+ return condb;
+ }
+ else if ( list->op == op_lparen )
+ {
+ int level = 1;
+ for ( conda = list->next, condb = list; level > 0;
+ condb = conda, conda = condb->next )
{
- /* 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 );
- }
+ if ( ! conda )
+ {
+ fprintf( stderr, "error in condition: brackets not paired\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 );
+ else if ( conda->op == op_lparen )
+ level ++;
+ else if ( conda->op == op_rparen )
+ level --;
}
+ return condb;
}
+ else
+ return NULL;
}
- if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )
+}
+
+
+
+/*
+ * Removing an expresion from beginning of the condition.
+ */
+static struct condition *skip_expr( struct condition *list )
+{
+ struct condition *conda, *condb;
+
+ condb = xtract_expr( list );
+ if ( condb )
{
- cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
- cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
- cond1d = cond1c->next;
+ conda = condb->next;
+ condb->next = NULL;
+ free_cond( list );
+ return conda;
+ }
+ return list;
+}
- if ( cond1c->op == op_constant
- && ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/
+
+
+/*
+ * Finding beginning of previous expr.
+ * Returns start of the previous expression and sets *cond to
+ * the preceiding operator (or NULL if there is none).
+ */
+static struct condition *skip_one_back( struct condition **cond, struct condition *list )
+{
+ struct condition *conda, *condb, *prev = NULL;
+
+ for ( conda = list; conda; prev = conda, conda = conda->next )
+ {
+ if ( conda->op == op_lparen || conda->op == op_variable ||
+ conda->op == op_true || conda->op == op_false )
{
- if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
+ condb = xtract_expr( conda );
+ if ( condb && condb->next == *cond )
+ {
+ *cond = prev;
+ return conda;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Finding previous "-o".
+ * Returns start of the previous expression and sets *cond to
+ * the preceiding operator (or NULL if there is none).
+ */
+static struct condition *skip_conj_back( struct condition **cond, struct condition *list )
+{
+ struct condition *prev = NULL;
+
+ {
+ prev = skip_one_back( cond, list );
+ } while ( *cond && (*cond)->op == op_and );
+ return prev;
+}
+
+
+
+/*
+ * Eliminating obviously true and obviously false conditions.
+ */
+static struct condition *eliminate_unneeded( struct condition *list, int level )
+{
+ struct condition *conda = list, *condb = NULL, *condc = NULL, *prev = NULL;
+ int start, eliminated = 1;
+
+ list = parse_eliminate_part( list );
+ for ( conda = list; conda && conda->next; conda = conda->next )
+ {
+ if ( conda->op == op_and || conda->op == op_or
+ || conda->op == op_lparen )
+ conda->next = parse_eliminate_part( conda->next );
+ }
+ while (eliminated)
+ {
+ eliminated = 0;
+ start = 1;
+ for ( conda = list; conda && conda->next;
+ prev = conda, conda = conda->next, start = 0 )
+ {
+repeat:
+ condb = conda->next; if ( condb == NULL ) goto done;
+ condc = condb->next; if ( condc == NULL ) goto done;
+ if ( conda->op == op_lparen )
+ {
+ conda->next = eliminate_unneeded( conda->next, level + 1 );
+ condb = conda->next; if ( condb == NULL ) goto done;
+ condc = condb->next; if ( condc == NULL ) goto done;
+ if ( conda->op == op_lparen
+ && (condb->op == op_true || condb->op == op_false)
+ && condc->op == op_rparen )
+ {
+ conda->op = condb->op;
+ conda->next = condc->next;
+ condc->next = NULL;
+ free_cond( condb );
+ eliminated = 1;
+ }
+ }
+ else if ( level > 0 && conda->op == op_rparen )
+ goto done;
+ else if ( (conda->op == op_false && condb->op == op_or && start)
+ || (conda->op == op_true && condb->op == op_and) )
+ {
+ condb->next = NULL;
+ free_cond( conda );
+ conda = condc;
+ if (start)
+ list = conda;
+ else
+ prev->next = conda;
+ eliminated = 1;
+ goto repeat;
+ }
+ else if ( (conda->op == op_false && condb->op == op_and)
+ || (conda->op == op_true && condb->op == op_or && start) )
+ {
+ condb->next = NULL;
+ free_cond( condb );
+ conda->next = skip_expr( condc );
+ eliminated = 1;
+ }
+ else if ( conda->op == op_or && condb->op == op_true
+ && condc->op == op_or )
+ {
+ condb->next = skip_expr( condc->next );
+ condc->next = NULL;
+ free_cond( condc );
+ eliminated = 1;
+ goto repeat;
+ }
+ else if ( conda->op == op_or && condb->op == op_false
+ && condc->op == op_or )
+ {
+ conda->next = condc->next;
+ condc->next = NULL;
+ free_cond( condb );
+ eliminated = 1;
+ }
+ else if ( conda->op == op_and && condb->op == op_true )
{
- cond1a->op = op_false;
- cond1a->next = NULL;
- free_cond( cond1b );
- return cond1a;
+ prev->next = condc;
+ condb->next = NULL;
+ free_cond( conda );
+ eliminated = 1;
+ goto done2;
+ }
+ else if ( conda->op == op_and && condb->op == op_false )
+ {
+ condc = conda;
+ prev = skip_one_back( &condc, list );
+ if ( prev )
+ {
+ conda->next = NULL;
+ if ( condc )
+ condc->next = condb;
+ else
+ list = condb;
+ free_cond( prev );
+ eliminated = 1;
+ goto done2;
+ }
+ }
+ }
+done:
+ /* Processing elimination at the end of the expresion */
+ if ( conda && ((conda->op == op_and && condb && condb->op == op_true)
+ || (conda->op == op_or && condb && condb->op == op_false &&
+ (!condc || condc->op != op_and))) )
+ {
+ prev->next = condc;
+ condb->next = NULL;
+ free_cond( conda );
+ eliminated = 1;
+ }
+ else if ( conda && conda->op == op_and && condb && condb->op == op_false )
+ {
+ condc = conda;
+ prev = skip_one_back( &condc, list );
+ if ( prev )
+ {
+ conda->next = NULL;
+ if ( condc )
+ condc->next = condb;
+ else
+ list = condb;
+ free_cond( prev );
+ eliminated = 1;
}
}
- else if ( cond1c->op == op_constant && cond1d->op == op_or )
+ else if ( conda && conda->op == op_or && condb && condb->op == op_true
+ && (!condc || condc->op != op_and) )
{
- if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
+ condc = conda;
+ prev = skip_conj_back( &condc, list );
+ if ( prev )
{
- cond1b = cond1d->next;
- cond1d->next = NULL;
- free_cond( cond1a );
- return eliminate_other_arch( cond1b );
+ conda->next = NULL;
+ if ( condc )
+ condc->next = condb;
+ else
+ list = condb;
+ free_cond( prev );
+ eliminated = 1;
}
}
+done2:;
}
-done:
return list;
}
@@ -453,7 +697,7 @@
case token_if:
cond_stack [depth++] =
- remove_bang( eliminate_other_arch( cfg->cond ) );
+ remove_bang( eliminate_unneeded( cfg->cond, 0 ) );
cfg->cond = NULL;
break;
@@ -490,15 +734,20 @@
--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:
+ if ( cfg->cond == NULL && cfg->nameindex > 0 )
+ {
+ vartable[cfg->nameindex].constant --;
+ vartable[cfg->nameindex].value = cfg->value;
+ }
+ case token_bool:
+ case token_choice_item:
+ case token_choice_header:
+ case token_comment:
case token_endmenu:
case token_hex:
case token_int:
@@ -506,6 +755,8 @@
case token_string:
case token_tristate:
case token_unset:
+ if ( cfg->nameindex > 0 )
+ vartable[cfg->nameindex].constant += 2;
cfg->cond = join_condition_stack( cond_stack, depth );
if ( cfg->cond && cfg->cond->op == op_false )
{
@@ -524,9 +775,11 @@
* Same as the other simple statements, plus an additional
* condition for the dependency.
*/
+ if ( cfg->nameindex > 0 )
+ vartable[cfg->nameindex].constant += 2;
if ( cfg->cond )
{
- cond_stack [depth] = eliminate_other_arch( cfg->cond );
+ cond_stack [depth] = eliminate_unneeded( cfg->cond, 0 );
cfg->cond = join_condition_stack( cond_stack, depth+1 );
}
else
@@ -536,7 +789,7 @@
if ( cfg->cond && cfg->cond->op == op_false )
{
good = 0;
- if ( prev )
+ if ( prev )
prev->next = cfg->next;
else
scfg = cfg->next;
@@ -565,7 +818,7 @@
printf( " %s", vartable[tmp->nameindex].name );
break;
case op_constant:
- printf( " %s", tmp->str );
+ printf( " \"%s\"", tmp->str );
break;
case op_eq:
printf( " =" );
diff -ur scripts.old/tkgen.c scripts/tkgen.c
--- scripts.old/tkgen.c Sat May 19 18:36:21 2001
+++ scripts/tkgen.c Sat Jul 28 23:08:21 2001
@@ -356,6 +356,17 @@
case op_lparen: printf( "(" ); break;
case op_rparen: printf( ")" ); break;
+ /*
+ * These shouldn't appear here. Just workaround for the case when
+ * something else is bad.
+ */
+ case op_true: printf( "\"1\" == \"1\"" );
+ fprintf( stderr, "Condition optimization problem\n" );
+ break;
+ case op_false: printf( "\"1\" == \"0\"" );
+ fprintf( stderr, "Condition optimization problem\n" );
+ break;
+
case op_variable:
printf( "$%s", vartable[cond->nameindex].name );
break;
@@ -722,6 +733,17 @@
case op_or: printf( " || " ); break;
case op_lparen: printf( "(" ); break;
case op_rparen: printf( ")" ); break;
+
+ /*
+ * These shouldn't appear here. Just workaround for the case when
+ * something else is bad.
+ */
+ case op_true: printf( "\"1\" == \"1\"" );
+ fprintf( stderr, "Condition optimization problem\n" );
+ break;
+ case op_false: printf( "\"1\" == \"0\"" );
+ fprintf( stderr, "Condition optimization problem\n" );
+ break;
case op_variable:
printf( "$%s", vartable[cond->nameindex].name );
diff -ur scripts.old/tkparse.h scripts/tkparse.h
--- scripts.old/tkparse.h Mon Feb 21 05:13:10 2000
+++ scripts/tkparse.h Tue Jul 3 21:39:57 2001
@@ -113,6 +113,8 @@
char * name;
char defined;
char global_written;
+ int constant;
+ char * value;
};
extern struct variable vartable[];
-- ======================================================================= Andrzej M. Krzysztofowicz ankry@mif.pg.gda.pl phone (48)(58) 347 14 61 Faculty of Applied Phys. & Math., Technical University of Gdansk - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/