* better
[mascara-docs.git] / i386 / linux-2.3.21 / scripts / tkcond.c
blobf1a36bb25be4f86646da57bc647739a10f8741ee
1 /*
2 * tkcond.c
4 * Eric Youngdale was the original author of xconfig.
5 * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
7 * This file takes the tokenized statement list and transforms 'if ...'
8 * statements. For each simple statement, I find all of the 'if' statements
9 * that enclose it, and attach the aggregate conditionals of those 'if'
10 * statements to the cond list of the simple statement.
12 * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
13 * - Steam-clean this file. I tested this by generating kconfig.tk for
14 * every architecture and comparing it character-for-character against
15 * the output of the old tkparse.
17 * 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
18 * - kvariables removed; all variables are stored in a single table now
19 * - some elimination of options non-valid for current architecture
20 * implemented.
21 * - negation (!) eliminated from conditions
23 * TO DO:
24 * - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
25 * you are interested in working on the replacement.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "tkparse.h"
37 * Mark variables which are defined anywhere.
39 static void mark_variables( struct kconfig * scfg )
41 struct kconfig * cfg;
42 int i;
44 for ( i = 1; i <= max_varnum; i++ )
45 vartable[i].defined = 0;
46 for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
48 if ( cfg->token == token_bool
49 || cfg->token == token_choice_item
50 || cfg->token == token_define_bool
51 || cfg->token == token_define_hex
52 || cfg->token == token_define_int
53 || cfg->token == token_define_string
54 || cfg->token == token_define_tristate
55 || cfg->token == token_dep_bool
56 || cfg->token == token_dep_tristate
57 || cfg->token == token_hex
58 || cfg->token == token_int
59 || cfg->token == token_string
60 || cfg->token == token_tristate
61 || cfg->token == token_unset )
63 if ( cfg->nameindex > 0 ) /* paranoid */
65 vartable[cfg->nameindex].defined = 1;
73 static void free_cond( struct condition *cond )
75 struct condition *tmp, *tmp1;
76 for ( tmp = cond; tmp; tmp = tmp1 )
78 tmp1 = tmp->next;
79 free( (void*)tmp );
86 * Remove the bang operator from a condition to avoid priority problems.
87 * "!" has different priorities as "test" command argument and in
88 * a tk script.
90 static struct condition * remove_bang( struct condition * condition )
92 struct condition * conda, * condb, * prev = NULL;
94 for ( conda = condition; conda; conda = conda->next )
96 if ( conda->op == op_bang && conda->next &&
97 ( condb = conda->next->next ) )
99 if ( condb->op == op_eq || condb->op == op_neq )
101 condb->op = (condb->op == op_eq) ? op_neq : op_eq;
102 conda->op = op_nuked;
103 if ( prev )
105 prev->next = conda->next;
107 else
109 condition = conda->next;
111 conda->next = NULL;
112 free_cond( conda );
113 conda = condb;
116 prev = conda;
118 return condition;
124 * Make a new condition chain by joining the current condition stack with
125 * the "&&" operator for glue.
127 static struct condition * join_condition_stack( struct condition * conditions [],
128 int depth )
130 struct condition * cond_list;
131 struct condition * cond_last;
132 int i, is_first = 1;
134 cond_list = cond_last = NULL;
136 for ( i = 0; i < depth; i++ )
138 if ( conditions[i]->op == op_false )
140 struct condition * cnew;
142 /* It is always false condition */
143 cnew = malloc( sizeof(*cnew) );
144 memset( cnew, 0, sizeof(*cnew) );
145 cnew->op = op_false;
146 cond_list = cond_last = cnew;
147 goto join_done;
150 for ( i = 0; i < depth; i++ )
152 struct condition * cond;
153 struct condition * cnew;
154 int add_paren;
156 /* omit always true conditions */
157 if ( conditions[i]->op == op_true )
158 continue;
160 /* if i have another condition, add an '&&' operator */
161 if ( !is_first )
163 cnew = malloc( sizeof(*cnew) );
164 memset( cnew, 0, sizeof(*cnew) );
165 cnew->op = op_and;
166 cond_last->next = cnew;
167 cond_last = cnew;
170 if ( conditions[i]->op != op_lparen )
172 /* add a '(' */
173 add_paren = 1;
174 cnew = malloc( sizeof(*cnew) );
175 memset( cnew, 0, sizeof(*cnew) );
176 cnew->op = op_lparen;
177 if ( cond_last == NULL )
178 { cond_list = cond_last = cnew; }
179 else
180 { cond_last->next = cnew; cond_last = cnew; }
182 else
184 add_paren = 0;
187 /* duplicate the chain */
188 for ( cond = conditions [i]; cond != NULL; cond = cond->next )
190 cnew = malloc( sizeof(*cnew) );
191 cnew->next = NULL;
192 cnew->op = cond->op;
193 cnew->str = cond->str ? strdup( cond->str ) : NULL;
194 cnew->nameindex = cond->nameindex;
195 if ( cond_last == NULL )
196 { cond_list = cond_last = cnew; }
197 else
198 { cond_last->next = cnew; cond_last = cnew; }
201 if ( add_paren )
203 /* add a ')' */
204 cnew = malloc( sizeof(*cnew) );
205 memset( cnew, 0, sizeof(*cnew) );
206 cnew->op = op_rparen;
207 cond_last->next = cnew;
208 cond_last = cnew;
210 is_first = 0;
214 * Remove duplicate conditions.
217 struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;
219 for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )
221 if ( cond1->op == op_lparen )
223 cond1b = cond1 ->next; if ( cond1b == NULL ) break;
224 cond1c = cond1b->next; if ( cond1c == NULL ) break;
225 cond1d = cond1c->next; if ( cond1d == NULL ) break;
226 cond1e = cond1d->next; if ( cond1e == NULL ) break;
227 cond1f = cond1e->next; if ( cond1f == NULL ) break;
229 if ( cond1b->op == op_variable
230 && ( cond1c->op == op_eq || cond1c->op == op_neq )
231 && cond1d->op == op_constant
232 && cond1e->op == op_rparen )
234 struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;
236 for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )
238 if ( cond2->op == op_lparen )
240 cond2b = cond2 ->next; if ( cond2b == NULL ) break;
241 cond2c = cond2b->next; if ( cond2c == NULL ) break;
242 cond2d = cond2c->next; if ( cond2d == NULL ) break;
243 cond2e = cond2d->next; if ( cond2e == NULL ) break;
244 cond2f = cond2e->next;
246 /* look for match */
247 if ( cond2b->op == op_variable
248 && cond2b->nameindex == cond1b->nameindex
249 && cond2c->op == cond1c->op
250 && cond2d->op == op_constant
251 && strcmp( cond2d->str, cond1d->str ) == 0
252 && cond2e->op == op_rparen )
254 /* one of these must be followed by && */
255 if ( cond1f->op == op_and
256 || ( cond2f != NULL && cond2f->op == op_and ) )
258 /* nuke the first duplicate */
259 cond1 ->op = op_nuked;
260 cond1b->op = op_nuked;
261 cond1c->op = op_nuked;
262 cond1d->op = op_nuked;
263 cond1e->op = op_nuked;
264 if ( cond1f->op == op_and )
265 cond1f->op = op_nuked;
266 else
267 cond2f->op = op_nuked;
277 join_done:
278 return cond_list;
283 static char * current_arch = NULL;
286 * Eliminating conditions with ARCH = <not current>.
288 static struct condition *eliminate_other_arch( struct condition *list )
290 struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;
291 if ( current_arch == NULL )
292 current_arch = getenv( "ARCH" );
293 if ( current_arch == NULL )
295 fprintf( stderr, "error: ARCH undefined\n" );
296 exit( 1 );
298 if ( cond1a->op == op_variable
299 && ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) )
301 cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
302 cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
303 cond1d = cond1c->next;
304 if ( cond1c->op == op_constant && cond1d == NULL )
306 if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
307 || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
309 /* This is for another architecture */
310 cond1a->op = op_false;
311 cond1a->next = NULL;
312 free_cond( cond1b );
313 return cond1a;
315 else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
316 || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
318 /* This is for current architecture */
319 cond1a->op = op_true;
320 cond1a->next = NULL;
321 free_cond( cond1b );
322 return cond1a;
325 else if ( cond1c->op == op_constant && cond1d->op == op_or )
327 if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
328 || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
330 /* This is for another architecture */
331 cond1b = cond1d->next;
332 cond1d->next = NULL;
333 free_cond( cond1a );
334 return eliminate_other_arch( cond1b );
336 else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
337 || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
339 /* This is for current architecture */
340 cond1a->op = op_true;
341 cond1a->next = NULL;
342 free_cond( cond1b );
343 return cond1a;
346 else if ( cond1c->op == op_constant && cond1d->op == op_and )
348 if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
349 || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
351 /* This is for another architecture */
352 int l_par = 0;
354 for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next )
356 if ( cond1c->op == op_lparen )
357 l_par++;
358 else if ( cond1c->op == op_rparen )
359 l_par--;
360 else if ( cond1c->op == op_or && l_par == 0 )
361 /* Expression too complex - don't touch */
362 return cond1a;
363 else if ( l_par < 0 )
365 fprintf( stderr, "incorrect condition: programming error ?\n" );
366 exit( 1 );
369 cond1a->op = op_false;
370 cond1a->next = NULL;
371 free_cond( cond1b );
372 return cond1a;
374 else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
375 || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
377 /* This is for current architecture */
378 cond1b = cond1d->next;
379 cond1d->next = NULL;
380 free_cond( cond1a );
381 return eliminate_other_arch( cond1b );
385 if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )
387 cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
388 cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
389 cond1d = cond1c->next;
391 if ( cond1c->op == op_constant
392 && ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/
394 if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
396 cond1a->op = op_false;
397 cond1a->next = NULL;
398 free_cond( cond1b );
399 return cond1a;
402 else if ( cond1c->op == op_constant && cond1d->op == op_or )
404 if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
406 cond1b = cond1d->next;
407 cond1d->next = NULL;
408 free_cond( cond1a );
409 return eliminate_other_arch( cond1b );
413 done:
414 return list;
420 * This is the main transformation function.
422 void fix_conditionals( struct kconfig * scfg )
424 struct kconfig * cfg;
427 * Transform op_variable to op_kvariable.
429 mark_variables( scfg );
432 * Walk the statement list, maintaining a stack of current conditions.
433 * token_if push its condition onto the stack.
434 * token_else invert the condition on the top of the stack.
435 * token_endif pop the stack.
437 * For a simple statement, create a condition chain by joining together
438 * all of the conditions on the stack.
441 struct condition * cond_stack [32];
442 int depth = 0;
443 struct kconfig * prev = NULL;
445 for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
447 int good = 1;
448 switch ( cfg->token )
450 default:
451 break;
453 case token_if:
454 cond_stack [depth++] =
455 remove_bang( eliminate_other_arch( cfg->cond ) );
456 cfg->cond = NULL;
457 break;
459 case token_else:
462 * Invert the condition chain.
464 * Be careful to transfrom op_or to op_and1, not op_and.
465 * I will need this later in the code that removes
466 * duplicate conditions.
468 struct condition * cond;
470 for ( cond = cond_stack [depth-1];
471 cond != NULL;
472 cond = cond->next )
474 switch( cond->op )
476 default: break;
477 case op_and: cond->op = op_or; break;
478 case op_or: cond->op = op_and1; break;
479 case op_neq: cond->op = op_eq; break;
480 case op_eq: cond->op = op_neq; break;
481 case op_true: cond->op = op_false;break;
482 case op_false:cond->op = op_true; break;
486 break;
488 case token_fi:
489 --depth;
490 break;
492 case token_bool:
493 case token_choice_item:
494 case token_choice_header:
495 case token_comment:
496 case token_define_bool:
497 case token_define_hex:
498 case token_define_int:
499 case token_define_string:
500 case token_define_tristate:
501 case token_hex:
502 case token_int:
503 case token_mainmenu_option:
504 case token_string:
505 case token_tristate:
506 case token_unset:
507 cfg->cond = join_condition_stack( cond_stack, depth );
508 if ( cfg->cond && cfg->cond->op == op_false )
510 good = 0;
511 if ( prev )
512 prev->next = cfg->next;
513 else
514 scfg = cfg->next;
516 break;
518 case token_dep_bool:
519 case token_dep_tristate:
521 * Same as the other simple statements, plus an additional
522 * condition for the dependency.
524 if ( cfg->cond )
526 cond_stack [depth] = eliminate_other_arch( cfg->cond );
527 cfg->cond = join_condition_stack( cond_stack, depth+1 );
529 else
531 cfg->cond = join_condition_stack( cond_stack, depth );
533 if ( cfg->cond && cfg->cond->op == op_false )
535 good = 0;
536 if ( prev )
537 prev->next = cfg->next;
538 else
539 scfg = cfg->next;
541 break;
543 if ( good )
544 prev = cfg;
551 #if 0
552 void dump_condition( struct condition *list )
554 struct condition *tmp;
555 for ( tmp = list; tmp; tmp = tmp->next )
557 switch (tmp->op)
559 default:
560 break;
561 case op_variable:
562 printf( " %s", vartable[tmp->nameindex].name );
563 break;
564 case op_constant:
565 printf( " %s", tmp->str );
566 break;
567 case op_eq:
568 printf( " =" );
569 break;
570 case op_bang:
571 printf( " !" );
572 break;
573 case op_neq:
574 printf( " !=" );
575 break;
576 case op_and:
577 case op_and1:
578 printf( " -a" );
579 break;
580 case op_or:
581 printf( " -o" );
582 break;
583 case op_true:
584 printf( " TRUE" );
585 break;
586 case op_false:
587 printf( " FALSE" );
588 break;
589 case op_lparen:
590 printf( " (" );
591 break;
592 case op_rparen:
593 printf( " )" );
594 break;
597 printf( "\n" );
599 #endif