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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [tools/] [src/] [libcdl/] [func.cxx] - Blame information for rev 1254

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

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

powered by: WebSVN 2.1.0

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