7 * The general idea here is that we want to parse a config.in file and
8 * from this, we generate a wish script which gives us effectively the
9 * same functionality that the original config.in script provided.
11 * This task is split roughly into 3 parts. The first parse is the parse
12 * of the input file itself. The second part is where we analyze the
13 * #ifdef clauses, and attach a linked list of tokens to each of the
14 * menu items. In this way, each menu item has a complete list of
15 * dependencies that are used to enable/disable the options.
16 * The third part is to take the configuration database we have build,
17 * and build the actual wish script.
19 * This file contains the code to further process the conditions from
20 * the "ifdef" clauses.
22 * The conditions are assumed to be one of the following formats
24 * simple_condition:= "$VARIABLE" == y/n/m
25 * simple_condition:= "$VARIABLE != y/n/m
27 * simple_condition -a simple_condition
29 * If the input condition contains '(' or ')' it would screw us up, but for now
30 * this is not a problem.
39 * Walk a condition chain and invert it so that the logical result is
42 static void invert_condition(struct condition
* cnd
)
45 * This is simple. Just walk through the list, and invert
46 * all of the operators.
48 for(;cnd
; cnd
= cnd
->next
)
57 * This is not turned into op_and - we need to keep track
58 * of what operators were used here since we have an optimization
59 * later on to remove duplicate conditions, and having
60 * inverted ors in there would make it harder if we did not
61 * distinguish an inverted or from an and we inserted because
79 * Walk a condition chain, and free the memory associated with it.
81 static void free_condition(struct condition
* cnd
)
83 struct condition
* next
;
88 if( cnd
->variable
.str
!= NULL
)
89 free(cnd
->variable
.str
);
96 * Walk all of the conditions, and look for choice values. Convert
97 * the tokens into something more digestible.
99 void fix_choice_cond(void)
101 struct condition
* cond
;
102 struct condition
* cond2
;
103 struct kconfig
* cfg
;
106 for(cfg
= config
;cfg
!= NULL
; cfg
= cfg
->next
)
108 if( cfg
->cond
== NULL
)
113 for(cond
= cfg
->cond
; cond
!= NULL
; cond
= cond
->next
)
115 if( cond
->op
!= op_kvariable
)
118 if( cond
->variable
.cfg
->tok
!= tok_choice
)
122 * Look ahead for what we are comparing this to. There should
123 * be one operator in between.
125 cond2
= cond
->next
->next
;
126 strcpy(tmpbuf
, cond
->variable
.cfg
->label
);
128 if( strcmp(cond2
->variable
.str
, "y") == 0 )
130 cond
->variable
.cfg
= cond
->variable
.cfg
->choice_label
;
131 cond2
->variable
.str
= strdup(tmpbuf
);
135 fprintf(stderr
,"tkparse can't handle this conditional\n");
144 * Walk the stack of conditions, and clone all of them with "&&" operators
145 * gluing them together. The conditions from each level of the stack
146 * are wrapped in parenthesis so as to guarantee that the results
147 * are logically correct.
149 struct condition
* get_token_cond(struct condition
** cond
, int depth
)
152 struct condition
* newcond
;
153 struct condition
* tail
;
154 struct condition
* new;
155 struct condition
* ocond
;
156 struct kconfig
* cfg
;
158 newcond
= tail
= NULL
;
159 for(i
=0; i
<depth
; i
++, cond
++)
162 * First insert the left parenthesis
164 new = (struct condition
*) malloc(sizeof(struct condition
));
165 memset(new, 0, sizeof(*new));
169 newcond
= tail
= new;
178 * Now duplicate the chain.
181 for(;ocond
!= NULL
; ocond
= ocond
->next
)
183 new = (struct condition
*) malloc(sizeof(struct condition
));
184 memset(new, 0, sizeof(*new));
186 if( ocond
->variable
.str
!= NULL
)
188 if( ocond
->op
== op_variable
)
191 * Search for structure to insert here.
193 for(cfg
= config
;cfg
!= NULL
; cfg
= cfg
->next
)
195 if( cfg
->tok
!= tok_bool
196 && cfg
->tok
!= tok_int
197 && cfg
->tok
!= tok_hex
198 && cfg
->tok
!= tok_string
199 && cfg
->tok
!= tok_tristate
200 && cfg
->tok
!= tok_choice
201 && cfg
->tok
!= tok_dep_tristate
)
205 if( strcmp(cfg
->optionname
, ocond
->variable
.str
) == 0)
207 new->variable
.cfg
= cfg
;
208 new->op
= op_kvariable
;
214 new->variable
.str
= strdup(ocond
->variable
.str
);
219 new->variable
.str
= strdup(ocond
->variable
.str
);
227 * Next insert the left parenthesis
229 new = (struct condition
*) malloc(sizeof(struct condition
));
230 memset(new, 0, sizeof(*new));
236 * Insert an and operator, if we have another condition.
240 new = (struct condition
*) malloc(sizeof(struct condition
));
241 memset(new, 0, sizeof(*new));
253 * Walk a single chain of conditions and clone it. These are assumed
254 * to be created/processed by get_token_cond in a previous pass.
256 struct condition
* get_token_cond_frag(struct condition
* cond
,
257 struct condition
** last
)
259 struct condition
* newcond
;
260 struct condition
* tail
;
261 struct condition
* new;
262 struct condition
* ocond
;
264 newcond
= tail
= NULL
;
267 * Now duplicate the chain.
269 for(ocond
= cond
;ocond
!= NULL
; ocond
= ocond
->next
)
271 new = (struct condition
*) malloc(sizeof(struct condition
));
272 memset(new, 0, sizeof(*new));
274 new->variable
.cfg
= ocond
->variable
.cfg
;
277 newcond
= tail
= new;
286 new = (struct condition
*) malloc(sizeof(struct condition
));
287 memset(new, 0, sizeof(*new));
297 * Walk through the if conditionals and maintain a chain.
299 void fix_conditionals(struct kconfig
* scfg
)
303 struct kconfig
* cfg
;
304 struct kconfig
* cfg1
;
305 struct condition
* conditions
[25];
306 struct condition
* cnd
;
307 struct condition
* cnd1
;
308 struct condition
* cnd2
;
309 struct condition
* cnd3
;
310 struct condition
* newcond
;
311 struct condition
* last
;
314 * Start by walking the chain. Every time we see an ifdef, push
315 * the condition chain on the stack. When we see an "else", we invert
316 * the condition at the top of the stack, and when we see an "endif"
317 * we free all of the memory for the condition at the top of the stack
318 * and remove the condition from the top of the stack.
320 * For any other type of token (i.e. a bool), we clone a new condition chain
321 * by anding together all of the conditions that are currently stored on
322 * the stack. In this way, we have a correct representation of whatever
323 * conditions govern the usage of each option.
325 memset(conditions
, 0, sizeof(conditions
));
326 for(cfg
=scfg
;cfg
!= NULL
; cfg
= cfg
->next
)
332 * Push this condition on the stack, and nuke the token
333 * representing the ifdef, since we no longer need it.
335 conditions
[depth
] = cfg
->cond
;
342 * For an else, we just invert the condition at the top of
343 * the stack. This is done in place with no reallocation
344 * of memory taking place.
346 invert_condition(conditions
[depth
-1]);
351 free_condition(conditions
[depth
]);
352 conditions
[depth
] = NULL
;
365 * We need to duplicate the chain of conditions and attach them to
368 cfg
->cond
= get_token_cond(&conditions
[0], depth
);
370 case tok_dep_tristate
:
372 * Same as tok_tristate et al except we have a temporary
373 * conditional. (Sort of a hybrid tok_if, tok_tristate, tok_fi
376 conditions
[depth
] = cfg
->cond
;
378 cfg
->cond
= get_token_cond(&conditions
[0], depth
);
380 free_condition(conditions
[depth
]);
381 conditions
[depth
] = NULL
;
388 * Fix any conditions involving the "choice" operator.
393 * Walk through and see if there are multiple options that control the
394 * same kvariable. If there are we need to treat them a little bit
397 for(cfg
=scfg
;cfg
!= NULL
; cfg
= cfg
->next
)
403 case tok_dep_tristate
:
407 for(cfg1
=cfg
;cfg1
!= NULL
; cfg1
= cfg1
->next
)
414 case tok_dep_tristate
:
418 if( strcmp(cfg
->optionname
, cfg1
->optionname
) == 0)
420 cfg
->flags
|= CFG_DUP
;
421 cfg1
->flags
|= CFG_DUP
;
435 * Now go through the list, and every time we see a kvariable, check
436 * to see whether it also has some dependencies. If so, then
437 * append it to our list. The reason we do this is that we might have
438 * option CONFIG_FOO which is only used if CONFIG_BAR is set. It may
439 * turn out that in config.in that the default value for CONFIG_BAR is
440 * set to "y", but that CONFIG_BAR is not enabled because CONFIG_XYZZY
441 * is not set. The current condition chain does not reflect this, but
442 * we can fix this by searching for the tokens that this option depends
443 * upon and cloning the conditions and merging them with the list.
445 for(cfg
=scfg
;cfg
!= NULL
; cfg
= cfg
->next
)
448 * Search for a token that has a condition list.
450 if(cfg
->cond
== NULL
) continue;
451 for(cnd
= cfg
->cond
; cnd
; cnd
=cnd
->next
)
454 * Now search the condition list for a known configuration variable
455 * that has conditions of its own.
457 if(cnd
->op
!= op_kvariable
) continue;
458 if(cnd
->variable
.cfg
->cond
== NULL
) continue;
460 if(cnd
->variable
.cfg
->flags
& CFG_DUP
) continue;
462 * OK, we have some conditions to append to cfg. Make a clone
465 newcond
= get_token_cond_frag(cnd
->variable
.cfg
->cond
, &last
);
468 * Finally, we splice it into our list.
470 last
->next
= cfg
->cond
;
477 * There is a strong possibility that we have duplicate conditions
478 * in here. It would make the script more efficient and readable to
479 * remove these. Here is where we assume here that there are no
480 * parenthesis in the input script.
482 for(cfg
=scfg
;cfg
!= NULL
; cfg
= cfg
->next
)
485 * Search for configuration options that have conditions.
487 if(cfg
->cond
== NULL
) continue;
488 for(cnd
= cfg
->cond
; cnd
; cnd
=cnd
->next
)
491 * Search for a left parenthesis.
493 if(cnd
->op
!= op_lparen
) continue;
494 for(cnd1
= cnd
->next
; cnd1
; cnd1
=cnd1
->next
)
497 * Search after the previous left parenthesis, and try
498 * and find a second left parenthesis.
500 if(cnd1
->op
!= op_lparen
) continue;
503 * Now compare the next 5 tokens to see if they are
504 * identical. We are looking for two chains that
505 * are like: '(' $VARIABLE operator constant ')'.
509 for(i
=0; i
<5; i
++, cnd2
=cnd2
->next
, cnd3
=cnd3
->next
)
511 if(!cnd2
|| !cnd3
) break;
512 if(cnd2
->op
!= cnd3
->op
) break;
513 if(i
== 1 && (cnd2
->op
!= op_kvariable
514 || cnd2
->variable
.cfg
!= cnd3
->variable
.cfg
) ) break;
515 if(i
==2 && cnd2
->op
!= op_eq
&& cnd2
->op
!= op_neq
) break;
516 if(i
== 3 && cnd2
->op
!= op_constant
&&
517 strcmp(cnd2
->variable
.str
, cnd3
->variable
.str
) != 0)
519 if(i
==4 && cnd2
->op
!= op_rparen
) break;
522 * If these match, and there is an and gluing these together,
523 * then we can nuke the second one.
525 if(i
==5 && ((cnd3
&& cnd3
->op
== op_and
)
526 ||(cnd2
&& cnd2
->op
== op_and
)))
529 * We have a duplicate. Nuke 5 ops.
532 for(i
=0; i
<5; i
++, cnd3
=cnd3
->next
)
537 * Nuke the and that glues the conditions together.
539 if(cnd3
&& cnd3
->op
== op_and
) cnd3
->op
= op_nuked
;
540 else if(cnd2
&& cnd2
->op
== op_and
) cnd2
->op
= op_nuked
;