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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//{{{  Banner                           
2
 
3
//============================================================================
4
//
5
//     option.cxx
6
//
7
//     Implementation of the CdlOption class
8
//
9
//============================================================================
10
// ####ECOSHOSTGPLCOPYRIGHTBEGIN####                                        
11
// -------------------------------------------                              
12
// This file is part of the eCos host tools.                                
13
// Copyright (C) 1999, 2000, 2002 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:        1999/03/01
37
// Version:     0.02
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
// <cdl.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 <cdl.hxx>
57
 
58
//}}}
59
 
60
//{{{  Statics                          
61
 
62
// ----------------------------------------------------------------------------
63
CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlOptionBody);
64
 
65
//}}}
66
//{{{  Constructor                      
67
 
68
// ----------------------------------------------------------------------------
69
CdlOptionBody::CdlOptionBody(std::string name_arg)
70
    : CdlNodeBody(name_arg),
71
      CdlUserVisibleBody(),
72
      CdlValuableBody(),
73
      CdlParentableBody(),
74
      CdlBuildableBody(),
75
      CdlDefinableBody()
76
{
77
    CYG_REPORT_FUNCNAME("CdlOptionBody:: constructor");
78
    CYG_REPORT_FUNCARG1XV(this);
79
 
80
    cdloptionbody_cookie = CdlOptionBody_Magic;
81
    CYGDBG_MEMLEAK_CONSTRUCTOR();
82
 
83
    CYG_POSTCONDITION_THISC();
84
    CYG_REPORT_RETURN();
85
}
86
 
87
//}}}
88
//{{{  Destructor                       
89
 
90
// ----------------------------------------------------------------------------
91
 
92
CdlOptionBody::~CdlOptionBody()
93
{
94
    CYG_REPORT_FUNCNAME("CdlOptionBody:: destructor");
95
    CYG_REPORT_FUNCARG1XV(this);
96
    CYG_PRECONDITION_THISC();
97
 
98
    cdloptionbody_cookie = CdlOptionBody_Invalid;
99
    CYGDBG_MEMLEAK_DESTRUCTOR();
100
 
101
    CYG_REPORT_RETURN();
102
}
103
 
104
//}}}
105
//{{{  parse_option()                   
106
 
107
// ----------------------------------------------------------------------------
108
// Parsing an option definition. This is basically the same as
109
// CdlComponent::parse_component(), but simpler: an option is not
110
// a container, and the only non-standard property is "parent".
111
 
112
int
113
CdlOptionBody::parse_option(CdlInterpreter interp, int argc, const char* argv[])
114
{
115
    CYG_REPORT_FUNCNAMETYPE("CdlOptionBody::parse_option", "result %d");
116
    CYG_REPORT_FUNCARG1("argc %d", argc);
117
    CYG_PRECONDITION_CLASSC(interp);
118
 
119
    std::string  diag_argv0      = CdlParse::get_tcl_cmd_name(argv[0]);
120
 
121
    CdlLoadable  loadable       = interp->get_loadable();
122
    CdlPackage   package        = dynamic_cast<CdlPackage>(loadable);
123
    CdlContainer parent         = interp->get_container();
124
    CdlToplevel  toplevel       = interp->get_toplevel();
125
    CYG_ASSERT_CLASSC(loadable);        // There should always be a loadable during parsing
126
    CYG_ASSERT_CLASSC(package);         // And packages are the only loadable for software CDL
127
    CYG_ASSERT_CLASSC(parent);
128
    CYG_ASSERT_CLASSC(toplevel);
129
 
130
    // The new option should be created and added to the package
131
    // early on. If there is a parsing error it will get cleaned up
132
    // automatically as a consequence of the package destructor.
133
    // However it is necessary to validate the name first. Errors
134
    // should be reported via CdlParse::report_error(),
135
    // which may result in an exception.
136
    CdlOption    new_option     = 0;
137
    bool         ok             = true;
138
    int          result         = TCL_OK;
139
    try {
140
 
141
        // Currently there are no command-line options. This may change in future.
142
        if (3 != argc) {
143
            CdlParse::report_error(interp, "",
144
                                   std::string("Incorrect number of arguments to `") + diag_argv0 +
145
                                         "'\nExpecting name and properties list.");
146
            ok = false;
147
        } else if (!Tcl_CommandComplete(CDL_TCL_CONST_CAST(char*, argv[2]))) {
148
            CdlParse::report_error(interp, "",
149
                                   std::string("Invalid property list for cdl_option `") + argv[1] + "'.");
150
            ok = false;
151
        } else if (0 != toplevel->lookup(argv[1])) {
152
            CdlParse::report_error(interp, "",
153
                                   std::string("Option `") + argv[1] + "' cannot be loaded.\nThe name is already in use.");
154
            ok = false;
155
        } else {
156
            new_option = new CdlOptionBody(argv[1]);
157
            toplevel->add_node(package, parent, new_option);
158
        }
159
 
160
        if (!ok) {
161
            // Just because this component cannot be created, that is no
162
            // reason to abort the whole parsing process.
163
            CYG_REPORT_RETVAL(TCL_OK);
164
            return TCL_OK;
165
        }
166
    } catch(std::bad_alloc e) {
167
        interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Out of memory"));
168
        result = TCL_ERROR;
169
    } catch(CdlParseException e) {
170
        interp->set_result(e.get_message());
171
        result = TCL_ERROR;
172
    } catch(...) {
173
        interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Unexpected C++ exception"));
174
        result = TCL_ERROR;
175
    }
176
    if (TCL_OK != result) {
177
        CYG_REPORT_RETVAL(result);
178
        return result;
179
    }
180
 
181
    // At this stage new_option has been created and added to the hierarchy.
182
    // The main work now is to add the properties.
183
 
184
    // Push the option as the current node early on. This aids
185
    // diagnostics.
186
    CdlNode old_node = interp->push_node(new_option);
187
 
188
    // Declare these outside the scope of the try statement, to allow
189
    // goto calls for the error handling.
190
    std::string tcl_result;
191
    std::vector<CdlInterpreterCommandEntry>  new_commands;
192
    std::vector<CdlInterpreterCommandEntry>* old_commands = 0;
193
    static CdlInterpreterCommandEntry commands[] =
194
    {
195
        CdlInterpreterCommandEntry("", 0 )
196
    };
197
    int i;
198
 
199
    // All parsing errors may result in an exception, under the control of
200
    // application code. This exception must not pass through the Tcl interpreter.
201
    try {
202
 
203
        for (i = 0; 0 != commands[i].command; i++) {
204
            new_commands.push_back(commands[i]);
205
        }
206
        CdlDefinableBody::add_property_parsers(new_commands);
207
        CdlBuildableBody::add_property_parsers(new_commands);
208
        CdlParentableBody::add_property_parsers(new_commands);
209
        CdlValuableBody::add_property_parsers(new_commands);
210
        CdlUserVisibleBody::add_property_parsers(new_commands);
211
        CdlNodeBody::add_property_parsers(new_commands);
212
 
213
        // Now evaluate the body. If an error occurs then typically
214
        // this will be reported via CdlParse::report_error(),
215
        // but any exceptions will have been intercepted and
216
        // turned into a Tcl error.
217
        old_commands = interp->push_commands(new_commands);
218
        result = interp->eval(argv[2], tcl_result);
219
        interp->pop_commands(old_commands);
220
 
221
        if (TCL_OK == result) {
222
            // Even if there were errors, they were not fatal. There may
223
            // now be a number of properties for this option, and some
224
            // validation should take place. Start with the base classes.
225
            new_option->CdlNodeBody::check_properties(interp);
226
            new_option->CdlUserVisibleBody::check_properties(interp);
227
            new_option->CdlValuableBody::check_properties(interp);
228
            new_option->CdlParentableBody::check_properties(interp);
229
            new_option->CdlBuildableBody::check_properties(interp);
230
            new_option->CdlDefinableBody::check_properties(interp);
231
        }
232
 
233
    } catch (std::bad_alloc e) {
234
        // Errors at this stage should be reported via Tcl, not via C++.
235
        // However there is no point in continuing with the parsing operation,
236
        // just give up.
237
        interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Out of memory"));
238
        result = TCL_ERROR;
239
    } catch (CdlParseException e) {
240
        interp->set_result(e.get_message());
241
        result = TCL_ERROR;
242
    } catch(...) {
243
        interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Unexpected C++ exception"));
244
        result = TCL_ERROR;
245
    }
246
 
247
    // Restore the interpreter to its prior state.
248
    interp->pop_node(old_node);
249
    if (0 != old_commands) {
250
        interp->pop_commands(old_commands);
251
    }
252
 
253
    CYG_REPORT_RETVAL(result);
254
    return result;
255
}
256
 
257
//}}}
258
//{{{  Persistence support              
259
 
260
// ----------------------------------------------------------------------------
261
void
262
CdlOptionBody::initialize_savefile_support(CdlToplevel toplevel)
263
{
264
    CYG_REPORT_FUNCNAME("CdlOption::initialize_savefile_support");
265
 
266
    toplevel->add_savefile_command("cdl_option", 0, &savefile_option_command);
267
    CdlValuableBody::initialize_savefile_support(toplevel, "cdl_option");
268
 
269
    CYG_REPORT_RETURN();
270
}
271
 
272
void
273
CdlOptionBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal)
274
{
275
    CYG_REPORT_FUNCNAME("CdlOption::save");
276
    CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal);
277
    CYG_PRECONDITION_THISC();
278
    CYG_PRECONDITION_CLASSC(interp);
279
 
280
    if (!minimal || this->has_additional_savefile_information() || this->value_savefile_entry_needed()) {
281
        // Start with the UserVisible data, which will result in a suitable set
282
        // of comments before the package definition itself.
283
        this->CdlUserVisibleBody::save(interp, chan, indentation, minimal);
284
 
285
        // Now output the line "cdl_option <name> {"
286
        // The name is guaranteed to be a valid C preprocessor symbol, so it
287
        // is not going to need any quoting.
288
        std::string data = std::string(indentation, ' ') + "cdl_option " + get_name() + " {\n";
289
        interp->write_data(chan, data);
290
 
291
        // Deal with the value
292
        bool modifiable = !(CdlValueFlavor_None == this->get_flavor()) &&
293
            !this->has_property(CdlPropertyId_Calculated);
294
        this->CdlValuableBody::save_valuable(interp, chan, indentation + 4, modifiable, minimal);
295
 
296
        // And with any unrecognised data
297
        this->CdlNodeBody::save(interp, chan, indentation + 4, minimal);
298
 
299
        // Close the cdl_option body. A blank line is added here.
300
        interp->write_data(chan, "};\n\n");
301
    }
302
 
303
    CYG_REPORT_RETURN();
304
}
305
 
306
int
307
CdlOptionBody::savefile_option_command(CdlInterpreter interp, int argc, const char* argv[])
308
{
309
    CYG_REPORT_FUNCNAMETYPE("CdlOption::savefile_option_command", "result %d");
310
    CYG_PRECONDITION_CLASSC(interp);
311
 
312
    int result = TCL_OK;
313
    CdlToplevel toplevel = interp->get_toplevel();
314
    CYG_ASSERT_CLASSC(toplevel);
315
    CdlConfiguration config = dynamic_cast<CdlConfiguration>(toplevel);
316
    CYG_ASSERT_CLASSC(config);
317
 
318
    std::vector<CdlInterpreterCommandEntry> subcommands;
319
    std::vector<CdlInterpreterCommandEntry>* toplevel_commands = 0;
320
    CdlNode old_node = 0;
321
 
322
    try {
323
 
324
        if (3 != argc) {
325
            CdlParse::report_error(interp, "", "Invalid cdl_option command in savefile, expecting two arguments.");
326
        } else {
327
 
328
            CdlNode current_node = config->lookup(argv[1]);
329
            if (0 == current_node) {
330
                // FIXME: save value in limbo
331
                CdlParse::report_error(interp, "",
332
                                       std::string("The savefile contains a cdl_option for an unknown option `")
333
                                       + argv[1] + "'");
334
            } else {
335
                config->get_savefile_subcommands("cdl_option", subcommands);
336
                toplevel_commands = interp->push_commands(subcommands);
337
                old_node = interp->push_node(current_node);
338
 
339
                std::string tcl_result;
340
                result = interp->eval(argv[2], tcl_result);
341
 
342
                interp->pop_commands(toplevel_commands);
343
                toplevel_commands = 0;
344
                interp->pop_node(old_node);
345
                old_node = 0;
346
            }
347
        }
348
    } catch(...) {
349
        if (0 != old_node) {
350
            interp->pop_node(old_node);
351
        }
352
        if (0 != toplevel_commands) {
353
            interp->pop_commands(toplevel_commands);
354
        }
355
        throw;
356
    }
357
 
358
    CYG_REPORT_RETVAL(result);
359
    return result;
360
}
361
 
362
//}}}
363
//{{{  check_this()                     
364
 
365
// ----------------------------------------------------------------------------
366
bool
367
CdlOptionBody::check_this(cyg_assert_class_zeal zeal) const
368
{
369
    if (CdlOptionBody_Magic != cdloptionbody_cookie) {
370
        return false;
371
    }
372
    CYGDBG_MEMLEAK_CHECKTHIS();
373
 
374
    return CdlNodeBody::check_this(zeal)        &&
375
           CdlUserVisibleBody::check_this(zeal) &&
376
           CdlValuableBody::check_this(zeal)    &&
377
           CdlParentableBody::check_this(zeal)  &&
378
           CdlBuildableBody::check_this(zeal)   &&
379
           CdlDefinableBody::check_this(zeal);
380
}
381
 
382
//}}}
383
//{{{  misc                             
384
 
385
// ----------------------------------------------------------------------------
386
 
387
std::string
388
CdlOptionBody::get_class_name() const
389
{
390
    CYG_REPORT_FUNCNAME("CdlOption::get_class_name");
391
    CYG_PRECONDITION_THISC();
392
    CYG_REPORT_RETURN();
393
    return "option";
394
}
395
 
396
//}}}

powered by: WebSVN 2.1.0

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