tkcond.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * tkcond.c
  3.  *
  4.  * Eric Youngdale was the original author of xconfig.
  5.  * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
  6.  *
  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.
  11.  *
  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.
  16.  *
  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
  22.  *
  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.
  26.  */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "tkparse.h"
  31. /*
  32.  * Mark variables which are defined anywhere.
  33.  */
  34. static void mark_variables( struct kconfig * scfg )
  35. {
  36.     struct kconfig * cfg;
  37.     int i;
  38.     for ( i = 1; i <= max_varnum; i++ )
  39. vartable[i].defined = 0;
  40.     for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
  41.     {
  42. if ( cfg->token == token_bool
  43. ||   cfg->token == token_choice_item
  44. ||   cfg->token == token_define_bool
  45. ||   cfg->token == token_define_hex
  46. ||   cfg->token == token_define_int
  47. ||   cfg->token == token_define_string
  48. ||   cfg->token == token_define_tristate
  49. ||   cfg->token == token_dep_bool
  50. ||   cfg->token == token_dep_mbool
  51. ||   cfg->token == token_dep_tristate
  52. ||   cfg->token == token_hex
  53. ||   cfg->token == token_int
  54. ||   cfg->token == token_string
  55. ||   cfg->token == token_tristate
  56. ||   cfg->token == token_unset )
  57. {
  58.     if ( cfg->nameindex > 0 ) /* paranoid */
  59.     {
  60. vartable[cfg->nameindex].defined = 1;
  61.     }
  62. }
  63.     }
  64. }
  65. static void free_cond( struct condition *cond )
  66. {
  67.     struct condition *tmp, *tmp1;
  68.     for ( tmp = cond; tmp; tmp = tmp1 )
  69.     {
  70. tmp1 = tmp->next;
  71. free( (void*)tmp );
  72.     }
  73. }
  74. /*
  75.  * Remove the bang operator from a condition to avoid priority problems.
  76.  * "!" has different priorities as "test" command argument and in 
  77.  * a tk script.
  78.  */
  79. static struct condition * remove_bang( struct condition * condition )
  80. {
  81.     struct condition * conda, * condb, * prev = NULL;
  82.     for ( conda = condition; conda; conda = conda->next )
  83.     {
  84. if ( conda->op == op_bang && conda->next &&
  85.    ( condb = conda->next->next ) )
  86. {
  87.     if ( condb->op == op_eq || condb->op == op_neq )
  88.     {
  89. condb->op = (condb->op == op_eq) ? op_neq : op_eq;
  90. conda->op = op_nuked;
  91. if ( prev )
  92. {
  93.     prev->next = conda->next;
  94. }
  95. else
  96. {
  97.     condition = conda->next;
  98. }
  99. conda->next = NULL;
  100. free_cond( conda );
  101. conda = condb;
  102.     }
  103. }
  104. prev = conda;
  105.     }
  106.     return condition;
  107. }
  108. /*
  109.  * Make a new condition chain by joining the current condition stack with
  110.  * the "&&" operator for glue.
  111.  */
  112. static struct condition * join_condition_stack( struct condition * conditions [],
  113.     int depth )
  114. {
  115.     struct condition * cond_list;
  116.     struct condition * cond_last;
  117.     int i, is_first = 1;
  118.     cond_list = cond_last = NULL;
  119.     for ( i = 0; i < depth; i++ )
  120.     {
  121. if ( conditions[i]->op == op_false )
  122. {
  123.     struct condition * cnew;
  124.     /* It is always false condition */
  125.     cnew = malloc( sizeof(*cnew) );
  126.     memset( cnew, 0, sizeof(*cnew) );
  127.     cnew->op = op_false;
  128.     cond_list = cond_last = cnew;
  129.     goto join_done;
  130. }
  131.     }
  132.     for ( i = 0; i < depth; i++ )
  133.     {
  134. struct condition * cond;
  135. struct condition * cnew;
  136. int add_paren;
  137. /* omit always true conditions */
  138. if ( conditions[i]->op == op_true )
  139.     continue;
  140. /* if i have another condition, add an '&&' operator */
  141. if ( !is_first )
  142. {
  143.     cnew = malloc( sizeof(*cnew) );
  144.     memset( cnew, 0, sizeof(*cnew) );
  145.     cnew->op = op_and;
  146.     cond_last->next = cnew;
  147.     cond_last = cnew;
  148. }
  149. if ( conditions[i]->op != op_lparen )
  150. {
  151.     /* add a '(' */
  152.     add_paren = 1;
  153.     cnew = malloc( sizeof(*cnew) );
  154.     memset( cnew, 0, sizeof(*cnew) );
  155.     cnew->op = op_lparen;
  156.     if ( cond_last == NULL )
  157. { cond_list = cond_last = cnew; }
  158.     else
  159. { cond_last->next = cnew; cond_last = cnew; }
  160. }
  161. else
  162. {
  163.     add_paren = 0;
  164. }
  165. /* duplicate the chain */
  166. for ( cond = conditions [i]; cond != NULL; cond = cond->next )
  167. {
  168.     cnew            = malloc( sizeof(*cnew) );
  169.     cnew->next      = NULL;
  170.     cnew->op        = cond->op;
  171.     cnew->str       = cond->str ? strdup( cond->str ) : NULL;
  172.     cnew->nameindex = cond->nameindex;
  173.     if ( cond_last == NULL )
  174. { cond_list = cond_last = cnew; }
  175.     else
  176. { cond_last->next = cnew; cond_last = cnew; }
  177. }
  178. if ( add_paren )
  179. {
  180.     /* add a ')' */
  181.     cnew = malloc( sizeof(*cnew) );
  182.     memset( cnew, 0, sizeof(*cnew) );
  183.     cnew->op = op_rparen;
  184.     cond_last->next = cnew;
  185.     cond_last = cnew;
  186. }
  187. is_first = 0;
  188.     }
  189.     /*
  190.      * Remove duplicate conditions.
  191.      */
  192.     {
  193. struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;
  194. for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )
  195. {
  196.     if ( cond1->op == op_lparen )
  197.     {
  198. cond1b = cond1 ->next; if ( cond1b == NULL ) break;
  199. cond1c = cond1b->next; if ( cond1c == NULL ) break;
  200. cond1d = cond1c->next; if ( cond1d == NULL ) break;
  201. cond1e = cond1d->next; if ( cond1e == NULL ) break;
  202. cond1f = cond1e->next; if ( cond1f == NULL ) break;
  203. if ( cond1b->op == op_variable
  204. && ( cond1c->op == op_eq || cond1c->op == op_neq )
  205. &&   cond1d->op == op_constant 
  206. &&   cond1e->op == op_rparen )
  207. {
  208.     struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;
  209.     for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )
  210.     {
  211. if ( cond2->op == op_lparen )
  212. {
  213.     cond2b = cond2 ->next; if ( cond2b == NULL ) break;
  214.     cond2c = cond2b->next; if ( cond2c == NULL ) break;
  215.     cond2d = cond2c->next; if ( cond2d == NULL ) break;
  216.     cond2e = cond2d->next; if ( cond2e == NULL ) break;
  217.     cond2f = cond2e->next;
  218.     /* look for match */
  219.     if ( cond2b->op == op_variable
  220.     &&   cond2b->nameindex == cond1b->nameindex
  221.     &&   cond2c->op == cond1c->op
  222.     &&   cond2d->op == op_constant
  223.     &&   strcmp( cond2d->str, cond1d->str ) == 0
  224.     &&   cond2e->op == op_rparen )
  225.     {
  226. /* one of these must be followed by && */
  227. if ( cond1f->op == op_and
  228. || ( cond2f != NULL && cond2f->op == op_and ) )
  229. {
  230.     /* nuke the first duplicate */
  231.     cond1 ->op = op_nuked;
  232.     cond1b->op = op_nuked;
  233.     cond1c->op = op_nuked;
  234.     cond1d->op = op_nuked;
  235.     cond1e->op = op_nuked;
  236.     if ( cond1f->op == op_and )
  237. cond1f->op = op_nuked;
  238.     else
  239. cond2f->op = op_nuked;
  240. }
  241.     }
  242. }
  243.     }
  244. }
  245.     }
  246. }
  247.     }
  248. join_done:
  249.     return cond_list;
  250. }
  251. static char * current_arch = NULL;
  252. /*
  253.  * Eliminating conditions with ARCH = <not current>.
  254.  */
  255. static struct condition *eliminate_other_arch( struct condition *list )
  256. {
  257.     struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;
  258.     if ( current_arch == NULL )
  259. current_arch = getenv( "ARCH" );
  260.     if ( current_arch == NULL )
  261.     {
  262. fprintf( stderr, "error: ARCH undefinedn" );
  263. exit( 1 );
  264.     }
  265.     if ( cond1a->op == op_variable
  266.     && ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) )
  267.     {
  268. cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
  269. cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
  270. cond1d = cond1c->next;
  271. if ( cond1c->op == op_constant && cond1d == NULL )
  272. {
  273.     if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
  274.     ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
  275.     {
  276. /* This is for another architecture */ 
  277. cond1a->op = op_false;
  278. cond1a->next = NULL;
  279. free_cond( cond1b );
  280. return cond1a;
  281.     }
  282.     else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
  283.  ||   (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
  284.     {
  285. /* This is for current architecture */
  286. cond1a->op = op_true;
  287. cond1a->next = NULL;
  288. free_cond( cond1b );
  289. return cond1a;
  290.     }
  291. }
  292. else if ( cond1c->op == op_constant && cond1d->op == op_or )
  293. {
  294.     if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
  295.     ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
  296.     {
  297. /* This is for another architecture */ 
  298. cond1b = cond1d->next;
  299. cond1d->next = NULL;
  300. free_cond( cond1a );
  301. return eliminate_other_arch( cond1b );
  302.     }
  303.     else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
  304.  || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
  305.     {
  306. /* This is for current architecture */
  307. cond1a->op = op_true;
  308. cond1a->next = NULL;
  309. free_cond( cond1b );
  310. return cond1a;
  311.     }
  312. }
  313. else if ( cond1c->op == op_constant && cond1d->op == op_and )
  314. {
  315.     if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
  316.     ||   (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
  317.     {
  318. /* This is for another architecture */
  319. int l_par = 0;
  320. for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next )
  321. {
  322.     if ( cond1c->op == op_lparen )
  323. l_par++;
  324.     else if ( cond1c->op == op_rparen )
  325. l_par--;
  326.     else if ( cond1c->op == op_or && l_par == 0 )
  327.     /* Expression too complex - don't touch */
  328. return cond1a;
  329.     else if ( l_par < 0 )
  330.     {
  331. fprintf( stderr, "incorrect condition: programming error ?n" );
  332. exit( 1 );
  333.     }
  334. }
  335. cond1a->op = op_false;
  336. cond1a->next = NULL;
  337. free_cond( cond1b );
  338. return cond1a;
  339.     }
  340.     else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
  341.  || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
  342.     {
  343. /* This is for current architecture */
  344. cond1b = cond1d->next;
  345. cond1d->next = NULL;
  346. free_cond( cond1a );
  347. return eliminate_other_arch( cond1b );
  348.     }
  349. }
  350.     }
  351.     if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )
  352.     {
  353. cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
  354. cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
  355. cond1d = cond1c->next;
  356. if ( cond1c->op == op_constant
  357. && ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/
  358. {
  359.     if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
  360.     {
  361. cond1a->op = op_false;
  362. cond1a->next = NULL;
  363. free_cond( cond1b );
  364. return cond1a;
  365.     }
  366. }
  367. else if ( cond1c->op == op_constant && cond1d->op == op_or )
  368. {
  369.     if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
  370.     {
  371. cond1b = cond1d->next;
  372. cond1d->next = NULL;
  373. free_cond( cond1a );
  374. return eliminate_other_arch( cond1b );
  375.     }
  376. }
  377.     }
  378. done:
  379.     return list;
  380. }
  381. /*
  382.  * This is the main transformation function.
  383.  */
  384. void fix_conditionals( struct kconfig * scfg )
  385. {
  386.     struct kconfig * cfg;
  387.     /*
  388.      * Transform op_variable to op_kvariable.
  389.      */
  390.     mark_variables( scfg );
  391.     /*
  392.      * Walk the statement list, maintaining a stack of current conditions.
  393.      *   token_if      push its condition onto the stack.
  394.      *   token_else    invert the condition on the top of the stack.
  395.      *   token_endif   pop the stack.
  396.      *
  397.      * For a simple statement, create a condition chain by joining together
  398.      * all of the conditions on the stack.
  399.      */
  400.     {
  401. struct condition * cond_stack [32];
  402. int depth = 0;
  403. struct kconfig * prev = NULL;
  404. for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
  405. {
  406.     int good = 1;
  407.     switch ( cfg->token )
  408.     {
  409.     default:
  410. break;
  411.     case token_if:
  412. cond_stack [depth++] =
  413.     remove_bang( eliminate_other_arch( cfg->cond ) );
  414. cfg->cond = NULL;
  415. break;
  416.     case token_else:
  417. {
  418.     /*
  419.      * Invert the condition chain.
  420.      *
  421.      * Be careful to transfrom op_or to op_and1, not op_and.
  422.      * I will need this later in the code that removes
  423.      * duplicate conditions.
  424.      */
  425.     struct condition * cond;
  426.     for ( cond  = cond_stack [depth-1];
  427.   cond != NULL;
  428.   cond  = cond->next )
  429.     {
  430. switch( cond->op )
  431. {
  432. default:     break;
  433. case op_and: cond->op = op_or;   break;
  434. case op_or:  cond->op = op_and1; break;
  435. case op_neq: cond->op = op_eq;   break;
  436. case op_eq:  cond->op = op_neq;  break;
  437. case op_true: cond->op = op_false;break;
  438. case op_false:cond->op = op_true; break;
  439. }
  440.     }
  441. }
  442. break;
  443.     case token_fi:
  444. --depth;
  445. break;
  446.     case token_bool:
  447.     case token_choice_item:
  448.     case token_choice_header:
  449.     case token_comment:
  450.     case token_define_bool:
  451.     case token_define_hex:
  452.     case token_define_int:
  453.     case token_define_string:
  454.     case token_define_tristate:
  455.     case token_endmenu:
  456.     case token_hex:
  457.     case token_int:
  458.     case token_mainmenu_option:
  459.     case token_string:
  460.     case token_tristate:
  461.     case token_unset:
  462. cfg->cond = join_condition_stack( cond_stack, depth );
  463. if ( cfg->cond && cfg->cond->op == op_false )
  464. {
  465.     good = 0;
  466.     if ( prev )
  467. prev->next = cfg->next;
  468.     else
  469. scfg = cfg->next;
  470. }
  471. break;
  472.     case token_dep_bool:
  473.     case token_dep_mbool:
  474.     case token_dep_tristate:
  475. /*
  476.  * Same as the other simple statements, plus an additional
  477.  * condition for the dependency.
  478.  */
  479. if ( cfg->cond )
  480. {
  481.     cond_stack [depth] = eliminate_other_arch( cfg->cond );
  482.     cfg->cond = join_condition_stack( cond_stack, depth+1 );
  483. }
  484. else
  485. {
  486.     cfg->cond = join_condition_stack( cond_stack, depth );
  487. }
  488. if ( cfg->cond && cfg->cond->op == op_false )
  489. {
  490.     good = 0;
  491.     if ( prev )
  492. prev->next = cfg->next;
  493.     else
  494. scfg = cfg->next;
  495. }
  496. break;
  497.     }
  498.     if ( good )
  499. prev = cfg;
  500. }
  501.     }
  502. }
  503. #if 0
  504. void dump_condition( struct condition *list )
  505. {
  506.     struct condition *tmp;
  507.     for ( tmp = list; tmp; tmp = tmp->next )
  508.     {
  509. switch (tmp->op)
  510. {
  511. default:
  512.     break;
  513. case op_variable:
  514.     printf( " %s", vartable[tmp->nameindex].name );
  515.     break;
  516. case op_constant: 
  517.     printf( " %s", tmp->str );
  518.     break;
  519. case op_eq:
  520.     printf( " =" );
  521.     break;
  522. case op_bang:
  523.     printf( " !" );
  524.     break;
  525. case op_neq:
  526.     printf( " !=" );
  527.     break;
  528. case op_and:
  529. case op_and1:
  530.     printf( " -a" );
  531.     break;
  532. case op_or:
  533.     printf( " -o" );
  534.     break;
  535. case op_true:
  536.     printf( " TRUE" );
  537.     break;
  538. case op_false:
  539.     printf( " FALSE" );
  540.     break;
  541. case op_lparen:
  542.     printf( " (" );
  543.     break;
  544. case op_rparen:
  545.     printf( " )" );
  546.     break;
  547. }
  548.     }
  549.     printf( "n" );
  550. }
  551. #endif