OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [bin/] [tkconfig/] [tkcond.c] - Blame information for rev 2

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.