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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [libcdl/] [func.cxx] - Blame information for rev 790

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//{{{  Banner                           
2
 
3
//============================================================================
4
//
5
//      func.cxx
6
//
7
//      Implementation of CDL functions
8
//
9
//============================================================================
10
// ####ECOSHOSTGPLCOPYRIGHTBEGIN####                                        
11
// -------------------------------------------                              
12
// This file is part of the eCos host tools.                                
13
// Copyright (C) 2001 Free Software Foundation, Inc.                        
14
//
15
// This program is free software; you can redistribute it and/or modify     
16
// it under the terms of the GNU General Public License as published by     
17
// the Free Software Foundation; either version 2 or (at your option) any   
18
// later version.                                                           
19
//
20
// This program is distributed in the hope that it will be useful, but      
21
// WITHOUT ANY WARRANTY; without even the implied warranty of               
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        
23
// General Public License for more details.                                 
24
//
25
// You should have received a copy of the GNU General Public License        
26
// along with this program; if not, write to the                            
27
// Free Software Foundation, Inc., 51 Franklin Street,                      
28
// Fifth Floor, Boston, MA  02110-1301, USA.                                
29
// -------------------------------------------                              
30
// ####ECOSHOSTGPLCOPYRIGHTEND####                                          
31
//============================================================================
32
//#####DESCRIPTIONBEGIN####
33
//
34
// Author(s):   bartv
35
// Contact(s):  bartv
36
// Date:        2001/04/20
37
// Version:     0.01
38
//
39
//####DESCRIPTIONEND####
40
//============================================================================
41
 
42
//}}}
43
//{{{  #include's                       
44
 
45
// ----------------------------------------------------------------------------
46
#include "cdlconfig.h"
47
 
48
// Get the infrastructure types, assertions, tracing and similar
49
// facilities.
50
#include <cyg/infra/cyg_ass.h>
51
#include <cyg/infra/cyg_trac.h>
52
 
53
// <cdlcore.hxx> defines everything implemented in this module.
54
// It implicitly supplies <string>, <vector> and <map> because
55
// the class definitions rely on these headers.
56
#include <cdlcore.hxx>
57
 
58
//}}}
59
 
60
//{{{  Core                             
61
 
62
// ----------------------------------------------------------------------------
63
int CdlFunction::next_id        = 1;
64
std::vector<CdlFunction*>       CdlFunction::all_functions;
65
 
66
// Dummy initializers, for e.g. when a particular function implementation does not
67
// support a certain type of inference.
68
void (*CdlFunction::null_check)(CdlExpression, const CdlSubexpression&) =
69
     (void (*)(CdlExpression, const CdlSubexpression&)) 0;
70
bool (*CdlFunction::null_infer_bool)(CdlTransaction, CdlExpression, unsigned int, bool, int) =
71
     (bool (*)(CdlTransaction, CdlExpression, unsigned int, bool, int)) 0;
72
bool (*CdlFunction::null_infer_value)(CdlTransaction, CdlExpression, unsigned int, CdlSimpleValue&, int) =
73
     (bool (*)(CdlTransaction, CdlExpression, unsigned int, CdlSimpleValue&, int)) 0;
74
 
75
 
76
CdlFunction::CdlFunction(const char* name_arg, int number_args_arg,
77
                         void (*check_arg)(CdlExpression, const CdlSubexpression&),
78
                         void (*eval_arg)(CdlEvalContext&, CdlExpression, const CdlSubexpression&, CdlSimpleValue&),
79
                         bool (*infer_bool_arg)(CdlTransaction, CdlExpression, unsigned int, bool, int),
80
                         bool (*infer_value_arg)(CdlTransaction, CdlExpression, unsigned int, CdlSimpleValue&, int))
81
    : name(name_arg),
82
      number_args(number_args_arg),
83
      check_fn(check_arg),
84
      eval_fn(eval_arg),
85
      infer_bool_fn(infer_bool_arg),
86
      infer_value_fn(infer_value_arg)
87
{
88
    id  = next_id++;
89
    all_functions.push_back(this);
90
}
91
 
92
CdlFunction::~CdlFunction()
93
{
94
}
95
 
96
bool
97
CdlFunction::is_function(std::string name, int& id)
98
{
99
    CYG_REPORT_FUNCNAMETYPE("CdlFunction::is_function", "result %d");
100
 
101
    bool result = false;
102
    std::vector<CdlFunction*>::const_iterator i;
103
 
104
    for (i = all_functions.begin(); !result && (i != all_functions.end()); i++) {
105
        if (name == (*i)->name) {
106
            result = true;
107
            id = (*i)->id;
108
        }
109
    }
110
 
111
    CYG_REPORT_RETVAL(result);
112
    return result;
113
}
114
 
115
std::string
116
CdlFunction::get_name(int id)
117
{
118
    CYG_REPORT_FUNCNAME("CdlFunction::get_name");
119
    CYG_REPORT_FUNCARG1XV(id);
120
 
121
    std::string result  = "";
122
    std::vector<CdlFunction*>::const_iterator i;
123
 
124
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
125
        if (id == (*i)->id) {
126
            result = (*i)->name;
127
            break;
128
        }
129
    }
130
 
131
    CYG_REPORT_RETURN();
132
    return result;
133
}
134
 
135
int
136
CdlFunction::get_args_count(int id)
137
{
138
    CYG_REPORT_FUNCNAMETYPE("CdlFunction::get_args_count", "result %d");
139
    CYG_REPORT_FUNCARG1XV(id);
140
 
141
    int result = 0;
142
    std::vector<CdlFunction*>::const_iterator i;
143
 
144
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
145
        if (id == (*i)->id) {
146
            result = (*i)->number_args;;
147
            break;
148
        }
149
    }
150
    CYG_REPORT_RETVAL(result);
151
    return result;
152
}
153
 
154
void
155
CdlFunction::check(CdlExpression expr, const CdlSubexpression& subexpr)
156
{
157
    CYG_REPORT_FUNCNAME("CdlFunction::check");
158
    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
159
 
160
    int id = subexpr.func;
161
    std::vector<CdlFunction*>::const_iterator i;
162
 
163
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
164
        if (id == (*i)->id) {
165
            if (CdlFunction::null_check != (*i)->check_fn) {
166
                (*((*i)->check_fn))(expr, subexpr);
167
            }
168
            break;
169
        }
170
    }
171
 
172
    CYG_REPORT_RETURN();
173
}
174
 
175
void
176
CdlFunction::eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
177
{
178
    CYG_REPORT_FUNCNAME("CdlFunction::eval");
179
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
180
 
181
    int id = subexpr.func;
182
    std::vector<CdlFunction*>::const_iterator i;
183
 
184
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
185
        if (id == (*i)->id) {
186
            (*((*i)->eval_fn))(context, expr, subexpr, result);
187
            break;
188
        }
189
    }
190
 
191
    CYG_REPORT_RETURN();
192
}
193
 
194
bool
195
CdlFunction::infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
196
{
197
    CYG_REPORT_FUNCNAMETYPE("CdlFunction::infer_bool", "result %d");
198
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
199
 
200
    bool result = false;
201
    CdlSubexpression& subexpr = expr->sub_expressions[index];
202
    int id = subexpr.func;
203
    std::vector<CdlFunction*>::const_iterator i;
204
 
205
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
206
        if (id == (*i)->id) {
207
            if (CdlFunction::null_infer_bool != (*i)->infer_bool_fn) {
208
                result = (*((*i)->infer_bool_fn))(transaction, expr, index, goal, level);
209
            }
210
            break;
211
        }
212
    }
213
 
214
    CYG_REPORT_RETVAL(result);
215
    return result;
216
}
217
 
218
bool
219
CdlFunction::infer_value(CdlTransaction transaction, CdlExpression expr, unsigned int index, CdlSimpleValue& goal, int level)
220
{
221
    CYG_REPORT_FUNCNAMETYPE("CdlFunction::infer_value", "result %d");
222
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, &goal, level);
223
 
224
    bool result = false;
225
    CdlSubexpression& subexpr = expr->sub_expressions[index];
226
    int id = subexpr.func;
227
    std::vector<CdlFunction*>::const_iterator i;
228
 
229
    for (i = all_functions.begin(); i != all_functions.end(); i++) {
230
        if (id == (*i)->id) {
231
            if (CdlFunction::null_infer_value != (*i)->infer_value_fn) {
232
                result = (*((*i)->infer_value_fn))(transaction, expr, index, goal, level);
233
            }
234
            break;
235
        }
236
    }
237
 
238
    CYG_REPORT_RETVAL(result);
239
    return result;
240
}
241
 
242
//}}}
243
//{{{  is_substr()                      
244
 
245
// ----------------------------------------------------------------------------
246
// is_substr(A, B)
247
//
248
// For example, is_substr(CYGBLD_GLOBAL_CFLAGS, " -fno-exceptions ")
249
//
250
// There is one subtlety about substring matching: what to do about the
251
// start and end of a string. If the specified substring begins with a
252
// space then this will match either a space or the start of the string,
253
// similarly for the final character.
254
 
255
static std::string::size_type
256
is_substr_find(std::string haystack, std::string needle, std::string::size_type& len_arg)
257
{
258
    CYG_REPORT_FUNCNAMETYPE("is_substr_find", "result %d");
259
    std::string::size_type result       = std::string::npos;
260
 
261
    std::string::size_type haystack_len = haystack.length();
262
    std::string::size_type needle_len   = needle.length();
263
 
264
    bool leading_space = false;
265
    bool trailing_space = false;
266
 
267
    if (' ' == needle[0]) {
268
        leading_space = true;
269
        needle_len--;
270
        needle = std::string(needle, 1, needle_len);
271
    }
272
    if (' ' == needle[needle_len - 1]) {
273
        trailing_space = true;
274
        needle_len--;
275
        needle = std::string(needle, 0, needle_len);
276
    }
277
 
278
    std::string::size_type posn = haystack.find(needle);
279
    while ((std::string::npos == result) && (std::string::npos != posn)) {
280
 
281
        std::string::size_type match_point = posn;
282
        bool match = true;
283
 
284
        // A possible match has been found. If there was a leading
285
        // space, check we are either at the start of the main string
286
        // or that a space is present.
287
        if (leading_space && (0 != posn) && (' ' != haystack[posn - 1])) {
288
            match = false;
289
        }
290
        if (trailing_space && (haystack_len != (posn + needle_len)) && (' ' != haystack[posn + needle_len])) {
291
            match = false;
292
        }
293
 
294
        // The result and len_arg returns exclude the spaces. This is deliberate.
295
        // Consider !is_substr("-g -O2 -fno-rtti -fno-exceptions", " -fnortti ").
296
        // If during inference the spaces were removed as well, this would give
297
        // "-g -O2-fno-exceptions", which is not desirable.
298
        if (match) {
299
            result  = match_point;
300
            len_arg = needle_len;
301
        } else {
302
            posn = haystack.find(needle, posn + 1);
303
        }
304
    }
305
 
306
    CYG_REPORT_RETVAL(result);
307
    return result;
308
}
309
 
310
static void
311
is_substr_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
312
{
313
    CYG_REPORT_FUNCNAME("is_substr_eval");
314
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
315
    CYG_PRECONDITION_CLASSOC(context);
316
    CYG_PRECONDITION_CLASSC(expr);
317
 
318
    CdlSimpleValue      arg0;
319
    CdlSimpleValue      arg1;
320
    expr->eval_subexpression(context, subexpr.args[0], arg0);
321
    expr->eval_subexpression(context, subexpr.args[1], arg1);
322
 
323
    std::string::size_type len;
324
    result = (std::string::npos != is_substr_find(arg0.get_value(), arg1.get_value(), len));
325
    CYG_REPORT_RETURN();
326
}
327
 
328
// Inference is only supported if the haystack argument is a reference that can be
329
// updated. The needle can be an arbitrary expression.
330
static bool
331
is_substr_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
332
{
333
    CYG_REPORT_FUNCNAMETYPE("is_substr_infer_bool", "result %d");
334
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
335
 
336
    bool result = false;
337
 
338
    CdlSubexpression& subexpr   = expr->sub_expressions[index];
339
    CdlSubexpression& arg0      = expr->sub_expressions[subexpr.args[0]];
340
    try {
341
        if (CdlExprOp_Reference == arg0.op) {
342
 
343
            CdlSimpleValue  needle_value;
344
            CdlEvalContext context(transaction);
345
            expr->eval_subexpression(context, subexpr.args[1], needle_value);
346
            std::string     needle  = needle_value.get_value();
347
 
348
            CdlNode         node        = expr->references[arg0.reference_index].get_destination();
349
            CdlValuable     valuable    = 0;
350
            if (0 != node) {
351
                valuable = dynamic_cast<CdlValuable>(node);
352
            }
353
            if ((0 != valuable) && ((CdlValueFlavor_BoolData == valuable->get_flavor()) ||
354
                                    (CdlValueFlavor_Data == valuable->get_flavor()))) {
355
                // OK, we have a valuable which can be given a suitable value.
356
                // What is the current string?
357
                const CdlValue& current_value   = transaction->get_whole_value(valuable);
358
                std::string haystack            = current_value.get_simple_value().get_value();
359
 
360
                // What is the goal? If the needle should be in the
361
                // haystack, append it if necessary. If the needle
362
                // should not be in the haystack, remove all current occurrences.
363
                if (goal) {
364
                    std::string::size_type len;
365
                    if (std::string::npos == is_substr_find(haystack, needle, len)) {
366
                        haystack = haystack + needle;
367
                    }
368
                } else {
369
                    std::string::size_type posn, len;
370
                    for (posn = is_substr_find(haystack, needle, len);
371
                         std::string::npos != posn;
372
                         posn = is_substr_find(haystack, needle, len)) {
373
                        haystack.erase(posn, len);
374
                    }
375
                }
376
 
377
                // OK, we have a new value for the haystack which should match the desired goal.
378
                // Try and set this value.
379
                CdlSimpleValue  new_value(haystack);
380
                result = CdlInfer::set_valuable_value(transaction, valuable, new_value, level);
381
            }
382
        }
383
    } catch (...) {
384
        result = false;
385
    }
386
 
387
    CYG_REPORT_RETVAL(result);
388
    return result;
389
}
390
 
391
static CdlFunction is_substr("is_substr", 2, CdlFunction::null_check, &is_substr_eval,
392
                             &is_substr_infer_bool, CdlFunction::null_infer_value);
393
 
394
//}}}
395
//{{{  is_xsubstr()                     
396
 
397
// ----------------------------------------------------------------------------
398
// is_xsubstr(A, B)
399
//
400
// Like is_substr() but only deals with exact matches, i.e. there is no special
401
// treatment for leading and trailing spaces in the needle.
402
 
403
static void
404
is_xsubstr_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
405
{
406
    CYG_REPORT_FUNCNAME("is_xsubstr_eval");
407
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
408
    CYG_PRECONDITION_CLASSOC(context);
409
    CYG_PRECONDITION_CLASSC(expr);
410
 
411
    CdlSimpleValue      arg0;
412
    CdlSimpleValue      arg1;
413
    expr->eval_subexpression(context, subexpr.args[0], arg0);
414
    expr->eval_subexpression(context, subexpr.args[1], arg1);
415
 
416
    result = (std::string::npos != arg0.get_value().find(arg1.get_value()));
417
    CYG_REPORT_RETURN();
418
}
419
 
420
// Inference is only supported if the haystack argument is a reference that can be
421
// updated. The needle can be an arbitrary expression.
422
static bool
423
is_xsubstr_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
424
{
425
    CYG_REPORT_FUNCNAMETYPE("is_xsubstr_infer_bool", "result %d");
426
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
427
 
428
    bool result = false;
429
 
430
    CdlSubexpression& subexpr   = expr->sub_expressions[index];
431
    CdlSubexpression& arg0      = expr->sub_expressions[subexpr.args[0]];
432
    try {
433
        if (CdlExprOp_Reference == arg0.op) {
434
 
435
            CdlSimpleValue  needle_value;
436
            CdlEvalContext context(transaction);
437
            expr->eval_subexpression(context, subexpr.args[1], needle_value);
438
            std::string     needle  = needle_value.get_value();
439
 
440
            CdlNode         node        = expr->references[arg0.reference_index].get_destination();
441
            CdlValuable     valuable    = 0;
442
            if (0 != node) {
443
                valuable = dynamic_cast<CdlValuable>(node);
444
            }
445
            if ((0 != valuable) && ((CdlValueFlavor_BoolData == valuable->get_flavor()) ||
446
                                    (CdlValueFlavor_Data == valuable->get_flavor()))) {
447
                // OK, we have a valuable which can be given a suitable value.
448
                // What is the current string?
449
                const CdlValue& current_value   = transaction->get_whole_value(valuable);
450
                std::string haystack            = current_value.get_simple_value().get_value();
451
 
452
                // What is the goal? If the needle should be in the
453
                // haystack, append it if necessary. If the needle
454
                // should not be in the haystack, remove all current occurrences.
455
                if (goal) {
456
                    if (std::string::npos == haystack.find(needle)) {
457
                        haystack = haystack + needle;
458
                    }
459
                } else {
460
                    std::string::size_type posn;
461
                    for (posn = haystack.find(needle); std::string::npos != posn; posn = haystack.find(needle)) {
462
                        haystack.erase(posn, needle.length());
463
                    }
464
                }
465
 
466
                // OK, we have a new value for the haystack which should match the desired goal.
467
                // Try and set this value.
468
                CdlSimpleValue  new_value(haystack);
469
                result = CdlInfer::set_valuable_value(transaction, valuable, new_value, level);
470
            }
471
        }
472
    } catch (...) {
473
        result = false;
474
    }
475
 
476
    CYG_REPORT_RETVAL(result);
477
    return result;
478
}
479
 
480
static CdlFunction is_xsubstr("is_xsubstr", 2, CdlFunction::null_check, &is_xsubstr_eval,
481
                              &is_xsubstr_infer_bool, CdlFunction::null_infer_value);
482
 
483
//}}}
484
//{{{  is_loaded()                      
485
 
486
// ----------------------------------------------------------------------------
487
// is_loaded(x)
488
// Check whether or not a particular configuration option is loaded.
489
// This takes a single argument which must be a reference. No
490
// inference is possible, since loading and unloading packages is
491
// currently beyond the scope of the inference engine.
492
 
493
static void
494
is_loaded_check(CdlExpression expr, const CdlSubexpression& subexpr)
495
{
496
    CYG_REPORT_FUNCNAME("is_loaded_check");
497
    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
498
 
499
    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
500
    if (CdlExprOp_Reference != arg0.op) {
501
        throw CdlParseException(std::string("The argument to is_loaded() should be a reference to a configuration option.\n") +
502
                                CdlParse::get_expression_error_location());
503
    }
504
 
505
    CYG_REPORT_RETURN();
506
}
507
 
508
static void
509
is_loaded_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
510
{
511
    CYG_REPORT_FUNCNAME("is_loaded_eval");
512
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
513
    CYG_PRECONDITION_CLASSOC(context);
514
    CYG_PRECONDITION_CLASSC(expr);
515
 
516
    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
517
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
518
 
519
    result = (0 != context.resolve_reference(expr, arg0.reference_index));
520
    CYG_REPORT_RETURN();
521
}
522
 
523
static CdlFunction is_loaded("is_loaded", 1, &is_loaded_check, &is_loaded_eval,
524
                             CdlFunction::null_infer_bool, CdlFunction::null_infer_value);
525
 
526
//}}}
527
//{{{  is_active()                      
528
 
529
// ----------------------------------------------------------------------------
530
// is_active(x)
531
// Check whether or not a particular configuration option is loaded
532
// and active. This takes a single argument which must be a reference.
533
 
534
static void
535
is_active_check(CdlExpression expr, const CdlSubexpression& subexpr)
536
{
537
    CYG_REPORT_FUNCNAME("is_active_check");
538
    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
539
 
540
    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
541
    if (CdlExprOp_Reference != arg0.op) {
542
        throw CdlParseException(std::string("The argument to is_active() should be a reference to a configuration option.\n") +
543
                                CdlParse::get_expression_error_location());
544
    }
545
 
546
    CYG_REPORT_RETURN();
547
}
548
 
549
static void
550
is_active_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
551
{
552
    CYG_REPORT_FUNCNAME("is_active_eval");
553
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
554
    CYG_PRECONDITION_CLASSOC(context);
555
    CYG_PRECONDITION_CLASSC(expr);
556
 
557
    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
558
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
559
 
560
    CdlNode node = context.resolve_reference(expr, arg0.reference_index);
561
    if (0 != node) {
562
        result = node->is_active(context.transaction);
563
    } else {
564
        result = false;
565
    }
566
    CYG_REPORT_RETURN();
567
}
568
 
569
static bool
570
is_active_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
571
{
572
    CYG_REPORT_FUNCNAMETYPE("is_active_infer_bool", "result %d");
573
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
574
 
575
    bool result = false;
576
 
577
    CdlSubexpression subexpr    = expr->sub_expressions[index];
578
    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
579
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
580
 
581
    CdlNode node = expr->references[arg0.reference_index].get_destination();
582
    if (0 != node) {
583
        if (goal) {
584
            result = CdlInfer::make_active(transaction, node, level);
585
        } else {
586
            result = CdlInfer::make_inactive(transaction, node, level);
587
        }
588
    }
589
 
590
    CYG_REPORT_RETVAL(result);
591
    return result;
592
}
593
 
594
static CdlFunction is_active("is_active", 1, &is_active_check, &is_active_eval,
595
                             &is_active_infer_bool, CdlFunction::null_infer_value);
596
 
597
//}}}
598
//{{{  is_enabled()                     
599
 
600
// ----------------------------------------------------------------------------
601
// is_enabled(x)
602
// Check whether or not a particular configuration option is loaded
603
// and enabled. The active/inactive state is ignored. This function
604
// takes a single argument which must be a reference.
605
 
606
static void
607
is_enabled_check(CdlExpression expr, const CdlSubexpression& subexpr)
608
{
609
    CYG_REPORT_FUNCNAME("is_enabled_check");
610
    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
611
 
612
    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
613
    if (CdlExprOp_Reference != arg0.op) {
614
        throw CdlParseException(std::string("The argument to is_enabled() should be a reference to a configuration option.\n") +
615
                                CdlParse::get_expression_error_location());
616
    }
617
 
618
    CYG_REPORT_RETURN();
619
}
620
 
621
static void
622
is_enabled_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
623
{
624
    CYG_REPORT_FUNCNAME("is_enabled_eval");
625
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
626
    CYG_PRECONDITION_CLASSOC(context);
627
    CYG_PRECONDITION_CLASSC(expr);
628
 
629
    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
630
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
631
 
632
    CdlValuable valuable = context.resolve_valuable_reference(expr, arg0.reference_index);
633
    if (0 != valuable) {
634
        if (0 != context.transaction) {
635
            result = valuable->is_enabled(context.transaction);
636
        } else {
637
            result = valuable->is_enabled();
638
        }
639
    } else {
640
        result = false;
641
    }
642
    CYG_REPORT_RETURN();
643
}
644
 
645
static bool
646
is_enabled_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
647
{
648
    CYG_REPORT_FUNCNAMETYPE("is_enabled_infer_bool", "result %d");
649
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
650
 
651
    bool result = false;
652
 
653
    CdlSubexpression subexpr    = expr->sub_expressions[index];
654
    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
655
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
656
 
657
    CdlNode node = expr->references[arg0.reference_index].get_destination();
658
    if (0 != node) {
659
        CdlValuable valuable    = dynamic_cast<CdlValuable>(node);
660
        if (0 != valuable) {
661
            // OK, we have found a valuable. Is it already enabled?
662
            // Does it have a boolean component? Is it modifiable? Has
663
            // it already been modified by the user in this transaction?
664
            if (goal == valuable->is_enabled()) {
665
                result = true;
666
            } else {
667
                CdlValueFlavor flavor = valuable->get_flavor();
668
                if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) {
669
                    if (valuable->is_modifiable()) {
670
                        if (!transaction->changed_by_user(valuable)) {
671
                            // We have a modifiable option and want to set the enabled flag.
672
                            // However we do not want to lose the current data part - unless
673
                            // some other constraint has caused that to be set.
674
                            const CdlValue& old_value   = transaction->get_whole_value(valuable);
675
                            CdlValue        new_value   = old_value;
676
                            if (!old_value.has_source(CdlValueSource_Inferred)) {
677
                                CdlSimpleValue simple_value = old_value.get_simple_value(CdlValueSource_Current);
678
                                new_value.set_value(simple_value, CdlValueSource_Inferred);
679
                            }
680
                            new_value.set_enabled(goal, CdlValueSource_Inferred);
681
                            new_value.set_source(CdlValueSource_Inferred);
682
                            transaction->set_whole_value(valuable, old_value, new_value);
683
                            result = transaction->resolve_recursion(level);
684
                        }
685
                    }
686
                }
687
            }
688
        }
689
    }
690
 
691
    CYG_REPORT_RETVAL(result);
692
    return result;
693
}
694
 
695
static CdlFunction is_enabled("is_enabled", 1, &is_enabled_check, &is_enabled_eval,
696
                              &is_enabled_infer_bool, CdlFunction::null_infer_value);
697
 
698
//}}}
699
//{{{  get_data()                       
700
 
701
// ----------------------------------------------------------------------------
702
// get_data(x)
703
// Returns "0" if the specified option is not enabled, otherwise
704
// the current data part fo the value. The active/inactive and the
705
// enabled states are ignored. This function takes a single argument
706
// which must be a reference.
707
 
708
static void
709
get_data_check(CdlExpression expr, const CdlSubexpression& subexpr)
710
{
711
    CYG_REPORT_FUNCNAME("get_data_check");
712
    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
713
 
714
    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
715
    if (CdlExprOp_Reference != arg0.op) {
716
        throw CdlParseException(std::string("The argument to get_data() should be a reference to a configuration option.\n") +
717
                                CdlParse::get_expression_error_location());
718
    }
719
 
720
    CYG_REPORT_RETURN();
721
}
722
 
723
static void
724
get_data_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
725
{
726
    CYG_REPORT_FUNCNAME("get_data_eval");
727
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
728
    CYG_PRECONDITION_CLASSOC(context);
729
    CYG_PRECONDITION_CLASSC(expr);
730
 
731
    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
732
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
733
 
734
    CdlValuable valuable = context.resolve_valuable_reference(expr, arg0.reference_index);
735
    if (0 != valuable) {
736
        if (0 != context.transaction) {
737
            result = valuable->get_value(context.transaction);
738
        } else {
739
            result = valuable->get_value();
740
        }
741
    } else {
742
        result = false;
743
    }
744
    CYG_REPORT_RETURN();
745
}
746
 
747
static bool
748
get_data_infer_value(CdlTransaction transaction, CdlExpression expr, unsigned int index,  CdlSimpleValue& goal, int level)
749
{
750
    CYG_REPORT_FUNCNAMETYPE("get_data_infer_value", "result %d");
751
    CYG_REPORT_FUNCARG5XV(transaction, expr, index, &goal, level);
752
 
753
    bool result = false;
754
 
755
    CdlSubexpression subexpr    = expr->sub_expressions[index];
756
    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
757
    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
758
 
759
    CdlNode node = expr->references[arg0.reference_index].get_destination();
760
    if (0 != node) {
761
        CdlValuable valuable    = dynamic_cast<CdlValuable>(node);
762
        if (0 != valuable) {
763
            // OK, we have found a valuable. Does it have a data component?
764
            // Does it already have the right value. Is it modifiable? Has
765
            // it already been modified by the user in this transaction?
766
            CdlValueFlavor flavor = valuable->get_flavor();
767
            if ((CdlValueFlavor_Data == flavor) || (CdlValueFlavor_BoolData == flavor)) {
768
                CdlSimpleValue current_value = valuable->get_simple_value(transaction);
769
                if (goal != current_value) {
770
                    if (valuable->is_modifiable()) {
771
                        if (!transaction->changed_by_user(valuable)) {
772
                            // We have a modifiable option and want to set the data part.
773
                            // However we do not want to lose the enabled part - unless
774
                            // some other constraint has caused that to be set.
775
                            const CdlValue& old_value   = transaction->get_whole_value(valuable);
776
                            CdlValue        new_value   = old_value;
777
                            if (!old_value.has_source(CdlValueSource_Inferred)) {
778
                                new_value.set_enabled(old_value.is_enabled(), CdlValueSource_Inferred);
779
                            }
780
                            new_value.set_value(goal, CdlValueSource_Inferred);
781
                            new_value.set_source(CdlValueSource_Inferred);
782
                            transaction->set_whole_value(valuable, old_value, new_value);
783
                            result = transaction->resolve_recursion(level);
784
                        }
785
                    }
786
                }
787
            }
788
        }
789
    }
790
 
791
    CYG_REPORT_RETVAL(result);
792
    return result;
793
}
794
 
795
static CdlFunction get_data("get_data", 1, &get_data_check, &get_data_eval,
796
                            CdlFunction::null_infer_bool, &get_data_infer_value);
797
 
798
//}}}
799
//{{{  version_cmp()                    
800
 
801
// ----------------------------------------------------------------------------
802
// version_cmp(a, b)
803
// Evaluate both arguments, interpret them as version strings, and then
804
// return -1, 0 or 1.
805
 
806
static void
807
version_cmp_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
808
{
809
    CYG_REPORT_FUNCNAME("version_cmp_eval");
810
    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
811
    CYG_PRECONDITION_CLASSOC(context);
812
    CYG_PRECONDITION_CLASSC(expr);
813
 
814
    CdlSimpleValue      arg0;
815
    CdlSimpleValue      arg1;
816
    expr->eval_subexpression(context, subexpr.args[0], arg0);
817
    expr->eval_subexpression(context, subexpr.args[1], arg1);
818
 
819
    result = (cdl_int) Cdl::compare_versions(arg0.get_value(), arg1.get_value());
820
 
821
    CYG_REPORT_RETURN();
822
}
823
 
824
static CdlFunction version_cmp("version_cmp", 2, CdlFunction::null_check, &version_cmp_eval,
825
                               CdlFunction::null_infer_bool, CdlFunction::null_infer_value);
826
 
827
//}}}

powered by: WebSVN 2.1.0

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