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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [libcdl/] [database.cxx] - Blame information for rev 609

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

Line No. Rev Author Line
1 26 unneback
//{{{  Banner                                                   
2
 
3
//============================================================================
4
//
5
//      database.cxx
6
//
7
//      Temporary implementation of the CdlPackagesDatabase class
8
//      Implementations of the temporary CdlTargetsDatabase and
9
//      CdlTemplatesDatabase classes.
10
//
11
//============================================================================
12
//####COPYRIGHTBEGIN####
13
//                                                                          
14
// ----------------------------------------------------------------------------
15
// Copyright (C) 2002 Bart Veer
16
// Copyright (C) 1999, 2000, 2001 Red Hat, Inc.
17
//
18
// This file is part of the eCos host tools.
19
//
20
// This program is free software; you can redistribute it and/or modify it 
21
// under the terms of the GNU General Public License as published by the Free 
22
// Software Foundation; either version 2 of the License, or (at your option) 
23
// any later version.
24
// 
25
// This program is distributed in the hope that it will be useful, but WITHOUT 
26
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
27
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
28
// more details.
29
// 
30
// You should have received a copy of the GNU General Public License along with
31
// this program; if not, write to the Free Software Foundation, Inc., 
32
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33
//
34
// ----------------------------------------------------------------------------
35
//                                                                          
36
//####COPYRIGHTEND####
37
//============================================================================
38
//#####DESCRIPTIONBEGIN####
39
//
40
// Author(s):   bartv
41
// Contact(s):  bartv
42
// Date:        1999/01/21
43
// Version:     0.02
44
//
45
//####DESCRIPTIONEND####
46
//============================================================================
47
 
48
//}}}
49
//{{{  #include's                                               
50
 
51
// ----------------------------------------------------------------------------
52
#include "cdlconfig.h"
53
 
54
// Get the infrastructure types, assertions, tracing and similar
55
// facilities.
56
#include <cyg/infra/cyg_ass.h>
57
#include <cyg/infra/cyg_trac.h>
58
 
59
// <cdl.hxx> defines everything implemented in this module.
60
// It implicitly supplies <string>, <vector> and <map> because
61
// the class definitions rely on these headers.
62
#include <cdl.hxx>
63
 
64
// strcmp() is useful when dealing with Tcl strings.
65
#include <cstring>
66
 
67
//}}}
68
 
69
//{{{  Statics                                                  
70
 
71
// ----------------------------------------------------------------------------
72
// Some test cases may want to read in a file other than
73
// "ecos.db", e.g. to facilitate testing the error conditions.
74
char*
75
CdlPackagesDatabaseBody::database_name = "ecos.db";
76
 
77
// Should warnings be issued for minor database inconsistencies?
78
bool CdlPackagesDatabaseBody::verbose_mode      = false;
79
 
80
// The new_package etc. commands need to store the name of the
81
// current package so that subsequent commands can do the right thing.
82
// Using constant strings as the key avoids typo problems.
83
const char*     dbparser_pkgname                = "::dbparser_pkgname";
84
const char*     dbparser_pkgdata                = "__cdl_dbparser_pkgdata";
85
const char*     dbparser_targetname             = "::dbparser_targetname";
86
const char*     dbparser_targetdata             = "__cdl_dbparser_targetdata";
87
const char*     dbparser_component_repository   = "::component_repository";
88
const char*     dbparser_database_key           = "__dbparser_key";       // for assoc data
89
const char*     template_description_key        = "__cdl_extract_template_description"; // ditto
90
const char*     template_packages_key           = "__cdl_extract_template_packages";
91
 
92
// These are useful for generating diagnostics.
93
static std::string diag_package = std::string("package ");
94
static std::string diag_target  = std::string("target ");
95
 
96
CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlPackagesDatabaseBody);
97
 
98
//}}}
99
//{{{  Tcl commands for the parser                              
100
 
101
//{{{  CdlDbParser class                                
102
 
103
// ----------------------------------------------------------------------------
104
// Commands that get invoked from inside the Tcl interpreter. These
105
// need access to the internals of the database objects, which can be
106
// achieved by making them static members of a CdlDbParser class.
107
 
108
class CdlDbParser {
109
  public:
110
    static int new_package(CdlInterpreter, int, const char*[]);
111
    static int package_description(CdlInterpreter, int, const char*[]);
112
    static int package_alias(CdlInterpreter, int, const char*[]);
113
    static int package_directory(CdlInterpreter, int, const char*[]);
114
    static int package_script(CdlInterpreter, int, const char*[]);
115
    static int package_hardware(CdlInterpreter, int, const char*[]);
116
 
117
    static int new_target(CdlInterpreter, int, const char*[]);
118
    static int target_description(CdlInterpreter, int, const char*[]);
119
    static int target_alias(CdlInterpreter, int, const char*[]);
120
    static int target_packages(CdlInterpreter, int, const char*[]);
121
    static int target_enable(CdlInterpreter, int, const char*[]);
122
    static int target_disable(CdlInterpreter, int, const char*[]);
123
    static int target_set_value(CdlInterpreter, int, const char*[]);
124
};
125
 
126
//}}}
127
//{{{  CdlDbParser::package-related                     
128
 
129
// ----------------------------------------------------------------------------
130
// package <name> <body>
131
 
132
int
133
CdlDbParser::new_package(CdlInterpreter interp, int argc, const char* argv[])
134
{
135
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::new_package", "result %d");
136
    CYG_REPORT_FUNCARG1XV(argc);
137
    CYG_PRECONDITION_CLASSC(interp);
138
 
139
    CdlPackagesDatabase db      = static_cast<CdlPackagesDatabase>(interp->get_assoc_data(dbparser_database_key));
140
    CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db);
141
 
142
    if (3 != argc) {
143
        if (argc < 2) {
144
            CdlParse::report_error(interp, "", "Invalid package command, missing name and contents.");
145
        } else if (argc == 2) {
146
            CdlParse::report_error(interp, diag_package + argv[1], "Invalid package command, missing body.");
147
        } else {
148
            CdlParse::report_error(interp, diag_package + argv[1],
149
                                   "Invalid package command, expecting just name and body.");
150
        }
151
        CYG_REPORT_RETVAL(TCL_OK);
152
        return TCL_OK;
153
    }
154
    std::string pkg_name        = argv[1];
155
 
156
    // Better make sure that this is not a duplicate definition.
157
    if (std::find(db->package_names.begin(), db->package_names.end(), pkg_name) != db->package_names.end()) {
158
        CdlParse::report_warning(interp, diag_package + pkg_name, "Duplicate package entry, ignoring second occurence.");
159
        CYG_REPORT_RETVAL(TCL_OK);
160
        return TCL_OK;
161
    }
162
 
163
    // The package data is constructed locally. It only gets added to
164
    // the database in the absence of errors.
165
    bool package_ok      = true;
166
    int  old_error_count = CdlParse::get_error_count(interp);
167
 
168
    CdlPackagesDatabaseBody::package_data package;
169
    package.description = "";
170
    package.directory   = "";
171
    package.script      = "";
172
    package.hardware    = false;
173
 
174
    // aliases and versions are vectors and will take care of themselves
175
    // And the name had better be valid as well.
176
    if (!Cdl::is_valid_cdl_name(pkg_name)) {
177
        CdlParse::report_error(interp, diag_package + pkg_name, "This is not a valid CDL name.");
178
    }
179
 
180
    // Sort out the commands, then invoke the script in argv[2]. There is
181
    // no need to worry about error recovery here, any errors will be
182
    // fatal anyway.
183
    CdlInterpreterCommandEntry commands[] = {
184
        CdlInterpreterCommandEntry("description", &CdlDbParser::package_description ),
185
        CdlInterpreterCommandEntry("alias",       &CdlDbParser::package_alias       ),
186
        CdlInterpreterCommandEntry("directory",   &CdlDbParser::package_directory   ),
187
        CdlInterpreterCommandEntry("script",      &CdlDbParser::package_script      ),
188
        CdlInterpreterCommandEntry("hardware",    &CdlDbParser::package_hardware    ),
189
        CdlInterpreterCommandEntry("",            0                                 )
190
    };
191
    CdlInterpreterBody::CommandSupport  cmds(interp, commands);
192
    CdlInterpreterBody::VariableSupport interp_name(interp, dbparser_pkgname, pkg_name);
193
    CdlInterpreterBody::AssocSupport    interp_data(interp, dbparser_pkgdata, static_cast<ClientData>(&package));
194
    int result = interp->eval(argv[2]);
195
    if (TCL_OK == result) {
196
 
197
        // The body has been parsed OK. Check that it is valid.
198
        if ("" == package.directory) {
199
            CdlParse::report_error(interp, diag_package + pkg_name, "Missing directory specification.");
200
        }
201
        if ("" == package.script) {
202
            CdlParse::report_error(interp, diag_package + pkg_name, "Missing script specification.");
203
        }
204
        if (0 == package.aliases.size()) {
205
            CdlParse::report_error(interp, diag_package + pkg_name, "At least one alias should be supplied.");
206
        }
207
 
208
        // Additional checks. Is the package directory actually present?
209
        // Note that there are scenarios where a package may be listed
210
        // in the database but not installed, e.g. an anoncvs checkout
211
        // of selected modules.
212
        if ("" != package.directory) {
213
            std::string repo = interp->get_variable(dbparser_component_repository);
214
            CYG_ASSERTC("" != repo);
215
 
216
            std::string pkgdir = repo + "/" + package.directory;
217
            if (!interp->is_directory(pkgdir)) {
218
                if (CdlPackagesDatabaseBody::verbose_mode) {
219
                    CdlParse::report_warning(interp, diag_package + pkg_name,
220
                                             std::string("This package is not present in the component repository.\n"
221
                                                         "There is no directory `") + pkgdir + "'.");
222
                }
223
                package_ok = false;
224
            } else {
225
 
226
                // Now look for version subdirectories. There should be at least one.
227
                std::vector<std::string> subdirs;
228
                unsigned int i;
229
                interp->locate_subdirs(pkgdir, subdirs);
230
                std::sort(subdirs.begin(), subdirs.end(), Cdl::version_cmp());
231
 
232
                for (i = 0; i < subdirs.size(); i++) {
233
                    if (("CVS" == subdirs[i]) || ("cvs" == subdirs[i])) {
234
                        continue;
235
                    }
236
                    if ("" != package.script) {
237
                        if (!(interp->is_file(pkgdir + "/" + subdirs[i] + "/cdl/" + package.script) ||
238
                              interp->is_file(pkgdir + "/" + subdirs[i] + "/" + package.script))) {
239
                            CdlParse::report_warning(interp, diag_package + pkg_name,
240
                                                     std::string("Version subdirectory `") + subdirs[i] +
241
                                                     "' does not have a CDL script `" + package.script + "'.");
242
                            continue;
243
                        }
244
                    }
245
                    package.versions.push_back(subdirs[i]);
246
                }
247
                if (0 == package.versions.size()) {
248
                    CdlParse::report_warning(interp, diag_package + pkg_name,
249
                                             "This package does not have any valid version subdirectories.");
250
                    package_ok = false;
251
                }
252
            }
253
        }
254
    }
255
 
256
    // If the package is still ok, now is the time to add it to the database.
257
    if (package_ok && (old_error_count == CdlParse::get_error_count(interp))) {
258
        db->package_names.push_back(pkg_name);
259
        db->packages[pkg_name] = package;
260
    }
261
 
262
    CYG_REPORT_RETVAL(result);
263
    return result;
264
}
265
 
266
// Syntax: description <text>
267
int
268
CdlDbParser::package_description(CdlInterpreter interp, int argc, const char* argv[])
269
{
270
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_description", "result %d");
271
    CYG_REPORT_FUNCARG1XV(argc);
272
    CYG_PRECONDITION_CLASSC(interp);
273
 
274
    std::string name = interp->get_variable(dbparser_pkgname);
275
    CYG_ASSERTC("" != name);
276
    CdlPackagesDatabaseBody::package_data* package =
277
        static_cast<CdlPackagesDatabaseBody::package_data*>(interp->get_assoc_data(dbparser_pkgdata));
278
 
279
    if (2 != argc) {
280
        CdlParse::report_error(interp, diag_package + name, "Invalid description, expecting a single string.");
281
    } else if ("" != package->description) {
282
        CdlParse::report_warning(interp, diag_package + name, "A package should have only one description.");
283
    } else {
284
        package->description = argv[1];
285
    }
286
 
287
    CYG_REPORT_RETVAL(TCL_OK);
288
    return TCL_OK;
289
}
290
 
291
// Syntax: alias <list>
292
// For example: alias { "This is an alias" another_alias dummy_name }
293
int
294
CdlDbParser::package_alias(CdlInterpreter interp, int argc, const char* argv[])
295
{
296
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_alias", "result %d");
297
    CYG_REPORT_FUNCARG1XV(argc);
298
    CYG_PRECONDITION_CLASSC(interp);
299
 
300
    std::string name = interp->get_variable(dbparser_pkgname);
301
    CYG_ASSERTC("" != name);
302
    CdlPackagesDatabaseBody::package_data* package =
303
        static_cast<CdlPackagesDatabaseBody::package_data*>(interp->get_assoc_data(dbparser_pkgdata));
304
 
305
    // There should be one argument, a list of valid packages.
306
    // Also, the alias command should be used only once
307
    if (2 != argc) {
308
        CdlParse::report_error(interp, diag_package + name,
309
                               "The alias command should be followed by a list of known aliases.");
310
    } else if (0 < package->aliases.size()) {
311
        CdlParse::report_warning(interp, diag_package + name, "There should be only one list of aliases.");
312
    } else {
313
        int          list_count     = 0;
314
        const char** list_entries   = 0;
315
        Tcl_Interp* tcl_interp      = interp->get_tcl_interpreter();
316
        if (TCL_OK != Tcl_SplitList(tcl_interp, CDL_TCL_CONST_CAST(char*, argv[1]), &list_count, CDL_TCL_CONST_CAST(char***, &list_entries))) {
317
            CdlParse::report_error(interp, diag_package + name, Tcl_GetStringResult(tcl_interp));
318
        } else {
319
            if (0 == list_count) {
320
                CdlParse::report_error(interp, diag_package + name, "At least one alias should be supplied.");
321
            } else {
322
                for (int i = 0; i < list_count; i++) {
323
                    package->aliases.push_back(list_entries[i]);
324
                }
325
            }
326
            Tcl_Free((char*)list_entries);
327
        }
328
    }
329
 
330
    CYG_REPORT_RETVAL(TCL_OK);
331
    return TCL_OK;
332
}
333
 
334
// Syntax: directory <path>
335
// The path is of course relative to the component repository.
336
int
337
CdlDbParser::package_directory(CdlInterpreter interp, int argc, const char* argv[])
338
{
339
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_directory", "result %d");
340
    CYG_REPORT_FUNCARG1XV(argc);
341
    CYG_PRECONDITION_CLASSC(interp);
342
 
343
    std::string name = interp->get_variable(dbparser_pkgname);
344
    CYG_ASSERTC("" != name);
345
    CdlPackagesDatabaseBody::package_data* package =
346
        static_cast<CdlPackagesDatabaseBody::package_data*>(interp->get_assoc_data(dbparser_pkgdata));
347
 
348
    // There should be exactly one argument, and the directory command
349
    // should be used only once.
350
    if (2 != argc) {
351
        CdlParse::report_error(interp, diag_package + name, "Only one directory can be specified.");
352
    } else if ("" != package->directory) {
353
        CdlParse::report_warning(interp, diag_package + name, "A package can be located in only one directory.");
354
    } else {
355
        package->directory = argv[1];
356
    }
357
    CYG_REPORT_RETVAL(TCL_OK);
358
    return TCL_OK;
359
}
360
 
361
// Syntax: hardware
362
// There are no arguments.
363
int
364
CdlDbParser::package_hardware(CdlInterpreter interp, int argc, const char* argv[])
365
{
366
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_hardware", "result %d");
367
    CYG_REPORT_FUNCARG1XV(argc);
368
    CYG_PRECONDITION_CLASSC(interp);
369
 
370
    std::string name = interp->get_variable(dbparser_pkgname);
371
    CYG_ASSERTC("" != name);
372
    CdlPackagesDatabaseBody::package_data* package =
373
        static_cast<CdlPackagesDatabaseBody::package_data*>(interp->get_assoc_data(dbparser_pkgdata));
374
 
375
    if (1 != argc) {
376
        CdlParse::report_error(interp, diag_package + name, "There should be no further data after hardware.");
377
    } else if (package->hardware) {
378
        CdlParse::report_warning(interp, diag_package + name, "The hardware property should be specified only once");
379
    } else {
380
        package->hardware    = true;
381
    }
382
 
383
    CYG_REPORT_RETVAL(TCL_OK);
384
    return TCL_OK;
385
}
386
 
387
// Syntax: script <filename>
388
int
389
CdlDbParser::package_script(CdlInterpreter interp, int argc, const char* argv[])
390
{
391
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_script", "result %d");
392
    CYG_REPORT_FUNCARG1XV(argc);
393
    CYG_PRECONDITION_CLASSC(interp);
394
 
395
    std::string name = interp->get_variable(dbparser_pkgname);
396
    CYG_ASSERTC("" != name);
397
    CdlPackagesDatabaseBody::package_data* package =
398
        static_cast<CdlPackagesDatabaseBody::package_data*>(interp->get_assoc_data(dbparser_pkgdata));
399
 
400
    // There should be exactly one argument, and the script command
401
    // should be used only once
402
    if (2 != argc) {
403
        CdlParse::report_error(interp, diag_package + name, "Only one CDL script can be specified.");
404
    } else if ("" != package->script) {
405
        CdlParse::report_warning(interp, diag_package + name, "A package can have only one starting CDL script.");
406
    } else {
407
        package->script = argv[1];
408
    }
409
 
410
    CYG_REPORT_RETVAL(TCL_OK);
411
    return TCL_OK;
412
}
413
 
414
//}}}
415
//{{{  CdlDbParser::target-related                      
416
 
417
// ----------------------------------------------------------------------------
418
// target <name> <body>
419
 
420
int
421
CdlDbParser::new_target(CdlInterpreter interp, int argc, const char* argv[])
422
{
423
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::new_target", "result %d");
424
    CYG_REPORT_FUNCARG1XV(argc);
425
    CYG_PRECONDITION_CLASSC(interp);
426
 
427
    CdlPackagesDatabase db      = static_cast<CdlPackagesDatabase>(interp->get_assoc_data(dbparser_database_key));
428
    CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db);
429
 
430
    if (3 != argc) {
431
        if (argc < 2) {
432
            CdlParse::report_error(interp, "", "Invalid target command, missing name and contents.");
433
        } else if (argc == 2) {
434
            CdlParse::report_error(interp, diag_target + argv[1], "Invalid target command, missing body.");
435
        } else {
436
            CdlParse::report_error(interp, diag_target + argv[1], "Invalid target command, expecting just name and body.");
437
        }
438
        CYG_REPORT_RETVAL(TCL_OK);
439
        return TCL_OK;
440
    }
441
 
442
    std::string target_name     = argv[1];
443
 
444
    // Better make sure that this is not a duplicate definition.
445
    if (std::find(db->target_names.begin(), db->target_names.end(), target_name) != db->target_names.end()) {
446
        CdlParse::report_warning(interp, diag_target + target_name,
447
                                 "Duplicate target entry, ignoring second occurence.");
448
        CYG_REPORT_RETVAL(TCL_OK);
449
        return TCL_OK;
450
    }
451
 
452
    // The target data is constructed locally. It only gets added to the
453
    // database in the absence of errors.
454
    bool target_ok = true;
455
    int old_error_count = CdlParse::get_error_count(interp);
456
 
457
    CdlPackagesDatabaseBody::target_data target;
458
    target.description = "";
459
    // aliases, packages and compiler_flags are vectors and will take care of themselves
460
 
461
    // Sort out the commands, then invoke the script in argv[2]. There is
462
    // no need to worry about error recovery here, any errors will be
463
    // fatal anyway.
464
    CdlInterpreterCommandEntry commands[] = {
465
        CdlInterpreterCommandEntry("description",    &CdlDbParser::target_description    ),
466
        CdlInterpreterCommandEntry("alias",          &CdlDbParser::target_alias          ),
467
        CdlInterpreterCommandEntry("packages",       &CdlDbParser::target_packages       ),
468
        CdlInterpreterCommandEntry("enable",         &CdlDbParser::target_enable         ),
469
        CdlInterpreterCommandEntry("disable",        &CdlDbParser::target_disable        ),
470
        CdlInterpreterCommandEntry("set_value",      &CdlDbParser::target_set_value      ),
471
        CdlInterpreterCommandEntry("",               0                                   )
472
    };
473
    CdlInterpreterBody::CommandSupport  interp_cmds(interp, commands);
474
    CdlInterpreterBody::VariableSupport interp_name(interp, dbparser_targetname, target_name);
475
    CdlInterpreterBody::AssocSupport    interp_data(interp, dbparser_targetdata, static_cast<ClientData>(&target));
476
    int result = interp->eval(argv[2]);
477
    if (TCL_OK == result) {
478
 
479
        if (0 == target.aliases.size()) {
480
            CdlParse::report_error(interp, diag_target + target_name, "At least one alias should be supplied.");
481
        }
482
 
483
        // There is no check for > 0 hardware packages. This is an unlikely
484
        // scenario but should be allowed for.
485
        // Add this target to the list.
486
    }
487
 
488
    if (target_ok && (old_error_count == CdlParse::get_error_count(interp))) {
489
        db->target_names.push_back(target_name);
490
        db->targets[target_name] = target;
491
    }
492
 
493
    CYG_REPORT_RETVAL(result);
494
    return result;
495
}
496
 
497
// Syntax: description <text>
498
int
499
CdlDbParser::target_description(CdlInterpreter interp, int argc, const char* argv[])
500
{
501
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_description", "result %d");
502
    CYG_REPORT_FUNCARG1XV(argc);
503
    CYG_PRECONDITION_CLASSC(interp);
504
 
505
    std::string name = interp->get_variable(dbparser_targetname);
506
    CYG_ASSERTC("" != name);
507
    CdlPackagesDatabaseBody::target_data* target =
508
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
509
 
510
    if (2 != argc) {
511
        CdlParse::report_error(interp, diag_target + name, "The target description should be a single string.");
512
    } else if ("" != target->description) {
513
        CdlParse::report_warning(interp, diag_target + name, "A target should have only one description.");
514
    } else {
515
        target->description = argv[1];
516
    }
517
 
518
    CYG_REPORT_RETVAL(TCL_OK);
519
    return TCL_OK;
520
}
521
 
522
// Syntax: alias <list>
523
// For example: alias { "This is an alias" another_alias dummy_name }
524
int
525
CdlDbParser::target_alias(CdlInterpreter interp, int argc, const char* argv[])
526
{
527
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_alias", "result %d");
528
    CYG_REPORT_FUNCARG1XV(argc);
529
    CYG_PRECONDITION_CLASSC(interp);
530
 
531
    std::string name = interp->get_variable(dbparser_targetname);
532
    CYG_ASSERTC("" != name);
533
    CdlPackagesDatabaseBody::target_data* target =
534
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
535
 
536
    // There should be one argument, a list of valid aliases
537
    // The alias command should be used only once
538
    if (2 != argc) {
539
        CdlParse::report_error(interp, diag_target + name, "The alias command should be followed by a list of known aliases");
540
    } else if (0 < target->aliases.size()) {
541
        CdlParse::report_warning(interp, diag_target + name, "There should be only one list of aliases.");
542
    } else {
543
        int          list_count     = 0;
544
        const char** list_entries   = 0;
545
        Tcl_Interp* tcl_interp      = interp->get_tcl_interpreter();
546
        if (TCL_OK != Tcl_SplitList(tcl_interp, CDL_TCL_CONST_CAST(char*, argv[1]), &list_count, CDL_TCL_CONST_CAST(char***, &list_entries))) {
547
            CdlParse::report_error(interp, diag_target + name, Tcl_GetStringResult(tcl_interp));
548
        } else {
549
            if (0 == list_count) {
550
                CdlParse::report_error(interp, diag_target + name, "At least one alias should be supplied.");
551
            } else {
552
                for (int i = 0; i < list_count; i++) {
553
                    target->aliases.push_back(list_entries[i]);
554
                }
555
            }
556
            Tcl_Free((char*)list_entries);
557
        }
558
    }
559
 
560
    CYG_REPORT_RETVAL(TCL_OK);
561
    return TCL_OK;
562
}
563
 
564
// Syntax: packages <list> ...
565
// For example: packages { CYGPKG_HAL_XXX CYGPKG_HAL_YYY }
566
int
567
CdlDbParser::target_packages(CdlInterpreter interp, int argc, const char* argv[])
568
{
569
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_packages", "result %d");
570
    CYG_REPORT_FUNCARG1XV(argc);
571
    CYG_PRECONDITION_CLASSC(interp);
572
 
573
    std::string name = interp->get_variable(dbparser_targetname);
574
    CYG_ASSERTC("" != name);
575
    CdlPackagesDatabaseBody::target_data* target =
576
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
577
 
578
    // There should be one argument, a list of valid packages.
579
    // The packages command should be used only once
580
    if (2 != argc) {
581
        CdlParse::report_error(interp, diag_target + name, "`packages' should be followed by a list of known packages.");
582
    } else if (0 < target->packages.size()) {
583
        CdlParse::report_warning(interp, diag_target + name, "There should be only one list of packages.");
584
    } else {
585
        int          list_count     = 0;
586
        const char** list_entries   = 0;
587
        Tcl_Interp* tcl_interp      = interp->get_tcl_interpreter();
588
        if (TCL_OK != Tcl_SplitList(tcl_interp, CDL_TCL_CONST_CAST(char*, argv[1]), &list_count, CDL_TCL_CONST_CAST(char***, &list_entries))) {
589
            CdlParse::report_error(interp, diag_target + name, Tcl_GetStringResult(tcl_interp));
590
        } else {
591
            // Allow for a dummy target spec, just in case it proves useful.
592
            if (0 != list_count) {
593
                for (int i = 0; i < list_count; i++) {
594
                    target->packages.push_back(list_entries[i]);
595
                }
596
            }
597
            Tcl_Free((char*)list_entries);
598
        }
599
    }
600
 
601
    CYG_REPORT_RETVAL(TCL_OK);
602
    return TCL_OK;
603
}
604
 
605
// Syntax: enable { opt1 opt2 ... }
606
// For example: enable { CYGPKG_HAL_ARM_CL7xxx_7211 }
607
int
608
CdlDbParser::target_enable(CdlInterpreter interp, int argc, const char* argv[])
609
{
610
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_enable", "result %d");
611
    CYG_REPORT_FUNCARG1XV(argc);
612
    CYG_PRECONDITION_CLASSC(interp);
613
 
614
    std::string name = interp->get_variable(dbparser_targetname);
615
    CYG_ASSERTC("" != name);
616
    CdlPackagesDatabaseBody::target_data* target =
617
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
618
 
619
    // There should be one argument, a list of valid flags.
620
    if (2 != argc) {
621
        CdlParse::report_error(interp, diag_target + name, "`enable' should be followed by a list of CDL options.");
622
    } else {
623
        int          list_count     = 0;
624
        const char** list_entries   = 0;
625
        Tcl_Interp* tcl_interp      = interp->get_tcl_interpreter();
626
        if (TCL_OK != Tcl_SplitList(tcl_interp, CDL_TCL_CONST_CAST(char*, argv[1]), &list_count, CDL_TCL_CONST_CAST(char***, &list_entries))) {
627
            CdlParse::report_error(interp, diag_target + name, Tcl_GetStringResult(tcl_interp));
628
        } else {
629
            for (int i = 0; i < list_count; i++) {
630
                target->enable.push_back(list_entries[i]);
631
            }
632
            Tcl_Free((char *) list_entries);
633
        }
634
    }
635
 
636
    CYG_REPORT_RETVAL(TCL_OK);
637
    return TCL_OK;
638
}
639
 
640
 
641
// Syntax: disable { opt1 opt2 ... }
642
// For example: disable { CYGPKG_HAL_ARM_CL7xxx_7111 }
643
int
644
CdlDbParser::target_disable(CdlInterpreter interp, int argc, const char* argv[])
645
{
646
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_disable", "result %d");
647
    CYG_REPORT_FUNCARG1XV(argc);
648
    CYG_PRECONDITION_CLASSC(interp);
649
 
650
    std::string name = interp->get_variable(dbparser_targetname);
651
    CYG_ASSERTC("" != name);
652
    CdlPackagesDatabaseBody::target_data* target =
653
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
654
 
655
    // There should be one argument, a list of valid flags.
656
    if (2 != argc) {
657
        CdlParse::report_error(interp, diag_target + name, "`disable' should be followed by a list of CDL options.");
658
    } else {
659
        int          list_count     = 0;
660
        const char** list_entries   = 0;
661
        Tcl_Interp* tcl_interp      = interp->get_tcl_interpreter();
662
        if (TCL_OK != Tcl_SplitList(tcl_interp, CDL_TCL_CONST_CAST(char*, argv[1]), &list_count, CDL_TCL_CONST_CAST(char***, &list_entries))) {
663
            CdlParse::report_error(interp, diag_target + name, Tcl_GetStringResult(tcl_interp));
664
        } else {
665
            for (int i = 0; i < list_count; i++) {
666
                target->disable.push_back(list_entries[i]);
667
            }
668
            Tcl_Free((char *) list_entries);
669
        }
670
    }
671
 
672
    CYG_REPORT_RETVAL(TCL_OK);
673
    return TCL_OK;
674
}
675
 
676
// Syntax: set_value <option> <value>
677
// For example: set_value CYGHWR_MEMSIZE 0x100000
678
int
679
CdlDbParser::target_set_value(CdlInterpreter interp, int argc, const char* argv[])
680
{
681
    CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_set_value", "result %d");
682
    CYG_REPORT_FUNCARG1XV(argc);
683
    CYG_PRECONDITION_CLASSC(interp);
684
 
685
    std::string name = interp->get_variable(dbparser_targetname);
686
    CYG_ASSERTC("" != name);
687
    CdlPackagesDatabaseBody::target_data* target =
688
        static_cast<CdlPackagesDatabaseBody::target_data*>(interp->get_assoc_data(dbparser_targetdata));
689
 
690
    // There should be one argument, a list of valid flags.
691
    if (3 != argc) {
692
        CdlParse::report_error(interp, diag_target + name, "`set_value' should be followed by an option name and its value.");
693
    } else {
694
        target->set_values.push_back(std::make_pair(std::string(argv[1]), std::string(argv[2])));
695
    }
696
 
697
    CYG_REPORT_RETVAL(TCL_OK);
698
    return TCL_OK;
699
}
700
 
701
//}}}
702
 
703
//}}}
704
//{{{  CdlPackagesDatabase:: creation                           
705
 
706
// ----------------------------------------------------------------------------
707
// The exported interface is make(). The hard work is done inside the
708
// constructor.
709
 
710
CdlPackagesDatabase
711
CdlPackagesDatabaseBody::make(std::string repo, CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn)
712
{
713
    CYG_REPORT_FUNCNAMETYPE("CdlPackagesDatabase::make", "database %p");
714
 
715
    // Where is the component repository? The location may come from the
716
    // parent or from an environment variable ECOS_REPOSITORY
717
    if ("" == repo) {
718
        char *env = getenv("ECOS_REPOSITORY");
719
        if (0 == env) {
720
            throw CdlInputOutputException(std::string("No component repository specified and no ") +
721
                                          std::string("ECOS_REPOSITORY environment variable"));
722
        } else {
723
            repo = env;
724
        }
725
    }
726
 
727
    // Replace any backslashes in the repository with forward slashes.
728
    // The latter are used throughout the library
729
    // NOTE: this is not i18n-friendly.
730
    for (unsigned int i = 0; i < repo.size(); i++) {
731
        if ('\\' == repo[i]) {
732
            repo[i] = '/';
733
        }
734
    }
735
    CdlPackagesDatabase result = new CdlPackagesDatabaseBody(repo, error_fn, warn_fn);
736
    CYG_REPORT_RETVAL(result);
737
    return result;
738
}
739
 
740
// ----------------------------------------------------------------------------
741
 
742
CdlPackagesDatabaseBody::CdlPackagesDatabaseBody(std::string repo, CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn)
743
{
744
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase:: constructor");
745
    CYG_PRECONDITIONC("" != repo);
746
 
747
    // There will be calls to check_this() while the database is evaluated,
748
    // so make sure that the database is valid first.
749
    component_repository                = repo;
750
    cdlpackagesdatabasebody_cookie      = CdlPackagesDatabaseBody_Magic;
751
 
752
    // We want to read in the entire packages file. Portability problems
753
    // can be largely eliminated by using a Tcl interpreter for this, but
754
    // under Windows there is a problem if the pathname is a cygwin one.
755
    // For now it is assumed that the supplied pathname is acceptable to
756
    // Tcl.
757
    //
758
    // No attempt is made at this stage to use a safe interpreter.
759
    // Some file I/O operations are needed while processing the data,
760
    // for example to check that a package is actually installed.
761
    // Additional file I/O may prove useful in future, e.g. to create
762
    // some or all of a database on the fly. Obviously some
763
    // restrictions are desirable (no modify access to the repository,
764
    // no network capabilities, and so on.) These have to be added
765
    // in future.
766
 
767
    CdlInterpreter interp = CdlInterpreterBody::make();
768
 
769
    try {
770
 
771
        CdlInterpreterBody::ContextSupport context(interp, database_name);
772
        CdlInterpreterCommandEntry commands[] =
773
        {
774
            CdlInterpreterCommandEntry("package",  &CdlDbParser::new_package  ),
775
            CdlInterpreterCommandEntry("target",   &CdlDbParser::new_target   ),
776
            CdlInterpreterCommandEntry("",         0                          )
777
        };
778
        CdlInterpreterBody::CommandSupport cmds(interp, commands);
779
        CdlInterpreterBody::DiagSupport diag(interp, error_fn, warn_fn);
780
        CdlInterpreterBody::AssocSupport assoc(interp, dbparser_database_key, static_cast<ClientData>(this));
781
        CdlInterpreterBody::VariableSupport var(interp, dbparser_component_repository, repo);
782
        interp->add_command("unknown", &CdlParse::unknown_command);
783
        CdlParse::clear_error_count(interp);
784
 
785
        // Ignore errors at this stage, instead check error count at the end.
786
        (void) interp->eval_file(component_repository + "/" + database_name);
787
 
788
        // Now start looking for templates. These should reside in the
789
        // templates subdirectory of the component repository. Each template
790
        // should be in its own directory, and inside each directory should
791
        // be versioned template files with a .ect extension.
792
        std::string templates_dir = repo + "/" + "templates";
793
        std::vector<std::string> subdirs;
794
        interp->locate_subdirs(templates_dir, subdirs);
795
 
796
        unsigned int i;
797
        for (i = 0; i < subdirs.size(); i++) {
798
            // Do not add the template to the known ones until we are sure there is
799
            // at least one valid template.
800
            std::vector<std::string> files;
801
            interp->locate_files(templates_dir + "/" + subdirs[i], files);
802
            unsigned int j;
803
            for (j = 0; j < files.size(); j++) {
804
                if ((4 < files[j].size()) && (".ect" == files[j].substr(files[j].size() - 4))) {
805
                    break;
806
                }
807
            }
808
            if (j != files.size()) {
809
                this->template_names.push_back(subdirs[i]);
810
                for ( ; j < files.size(); j++) {
811
                    if ((4 < files[j].size()) && (".ect" == files[j].substr(files[j].size() - 4))) {
812
                        this->templates[subdirs[i]].versions.push_back(files[j].substr(0, files[j].size() - 4));
813
                    }
814
                }
815
            }
816
        }
817
 
818
        // Consistency checks. All target-specific packages should
819
        // have the hardware attribute. Also, all the packages should
820
        // exist. Problems only result in warnings and only when
821
        // operating in verbose mode, to allow for somewhat
822
        // inconsistent repositories e.g. an anoncvs tree.
823
        if (CdlPackagesDatabaseBody::verbose_mode) {
824
            std::vector<std::string>::const_iterator name_i;
825
            std::vector<std::string>::const_iterator name_j;
826
            for (name_i = target_names.begin(); name_i != target_names.end(); name_i++) {
827
                for (name_j = targets[*name_i].packages.begin(); name_j != targets[*name_i].packages.end(); name_j++) {
828
                    if (std::find(package_names.begin(), package_names.end(), *name_j) == package_names.end()) {
829
                        CdlParse::report_warning(interp, diag_target + *name_i,
830
                                                 std::string("This target refers to an unknown package `") + *name_j + "'.");
831
                    }
832
                    if (!packages[*name_j].hardware) {
833
                        CdlParse::report_warning(interp, diag_target + *name_i,
834
                                                 std::string("This target refers to a package `") + *name_j +
835
                                                 "' that is not hardware-specific.");
836
                    }
837
                }
838
            }
839
        }
840
        // Now, were there any errors while reading in the database?
841
        // If so it is necessary to throw an exception here, to make sure
842
        // that things get cleaned up properly.
843
        int error_count = CdlParse::get_error_count(interp);
844
        if (0 != error_count) {
845
            throw CdlInputOutputException("Invalid package database.");
846
        }
847
    } catch(...) {
848
        // Something has gone wrong. Clear out all of the data accumulated so far, as well
849
        // as the interpreter.
850
        delete interp;
851
        package_names.clear();
852
        target_names.clear();
853
        template_names.clear();
854
        packages.clear();
855
        targets.clear();
856
        templates.clear();
857
        throw;
858
    }
859
 
860
    delete interp;
861
    CYGDBG_MEMLEAK_CONSTRUCTOR();
862
 
863
    CYG_REPORT_RETURN();
864
}
865
 
866
//}}}
867
//{{{  CdlPackagesDatabase:: destructor                         
868
 
869
// ----------------------------------------------------------------------------
870
CdlPackagesDatabaseBody::~CdlPackagesDatabaseBody()
871
{
872
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase:: default destructor");
873
    CYG_REPORT_FUNCARG1XV(this);
874
    CYG_PRECONDITION_THISC();
875
 
876
    cdlpackagesdatabasebody_cookie      = CdlPackagesDatabaseBody_Invalid;
877
    component_repository                = "";
878
    package_names.clear();
879
    target_names.clear();
880
    template_names.clear();
881
    packages.clear();
882
    targets.clear();
883
    templates.clear();
884
 
885
    CYGDBG_MEMLEAK_DESTRUCTOR();
886
 
887
    CYG_REPORT_RETURN();
888
}
889
 
890
//}}}
891
//{{{  CdlPackagesDatabase:: check_this()                       
892
 
893
// ----------------------------------------------------------------------------
894
 
895
bool
896
CdlPackagesDatabaseBody::check_this(cyg_assert_class_zeal zeal) const
897
{
898
    if (CdlPackagesDatabaseBody_Magic != cdlpackagesdatabasebody_cookie) {
899
        return false;
900
    }
901
    CYGDBG_MEMLEAK_CHECKTHIS();
902
 
903
    switch(zeal) {
904
      case cyg_system_test :
905
      case cyg_extreme :
906
      {
907
          std::vector<std::string>::const_iterator              names_i;
908
          std::map<std::string,package_data>::const_iterator    pkgs_i;
909
 
910
          // Every entry in the names vector should have an entry in the packages vector.
911
          for (names_i = package_names.begin(); names_i != package_names.end(); names_i++) {
912
              if (packages.find(*names_i) == packages.end()) {
913
                  return false;
914
              }
915
          }
916
          // The inverse should be true as well
917
          for (pkgs_i = packages.begin(); pkgs_i != packages.end(); pkgs_i++) {
918
              if (std::find(package_names.begin(), package_names.end(), pkgs_i->first) == package_names.end()) {
919
                  return false;
920
              }
921
          }
922
 
923
          // Repeat for targets.
924
          std::map<std::string,target_data>::const_iterator     targets_i;
925
          for (names_i = target_names.begin(); names_i != target_names.end(); names_i++) {
926
              if (targets.find(*names_i) == targets.end()) {
927
                  return false;
928
              }
929
          }
930
          for (targets_i = targets.begin(); targets_i != targets.end(); targets_i++) {
931
              if (std::find(target_names.begin(), target_names.end(), targets_i->first) == target_names.end()) {
932
                  return false;
933
              }
934
          }
935
 
936
          // And for templates
937
          std::map<std::string,template_data>::const_iterator    templates_i;
938
          for (names_i = template_names.begin(); names_i != template_names.end(); names_i++) {
939
              if (templates.find(*names_i) == templates.end()) {
940
                  return false;
941
              }
942
          }
943
          // The inverse should be true as well
944
          for (templates_i = templates.begin(); templates_i != templates.end(); templates_i++) {
945
              if (std::find(template_names.begin(), template_names.end(), templates_i->first) == template_names.end()) {
946
                  return false;
947
              }
948
          }
949
 
950
          // Possibly the package directories should be validated as
951
          // well, not to mention the various version subdirectories,
952
          // but doing file I/O inside an assertion is excessive.
953
      }
954
      case cyg_thorough :
955
      case cyg_quick:
956
          if ("" == component_repository) {
957
              return false;
958
          }
959
      case cyg_trivial:
960
      case cyg_none :
961
        break;
962
    }
963
 
964
    return true;
965
}
966
 
967
//}}}
968
//{{{  CdlPackagesDatabase:: misc                               
969
 
970
// ----------------------------------------------------------------------------
971
 
972
std::string
973
CdlPackagesDatabaseBody::get_component_repository() const
974
{
975
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_component_repository");
976
    CYG_REPORT_FUNCARG1XV(this);
977
    CYG_PRECONDITION_THISC();
978
 
979
    CYG_REPORT_RETURN();
980
    return component_repository;
981
}
982
 
983
void
984
CdlPackagesDatabaseBody::set_verbose(bool new_mode)
985
{
986
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::set_verbose");
987
    CYG_REPORT_FUNCARG1XV(new_mode);
988
 
989
    verbose_mode = new_mode;
990
 
991
    CYG_REPORT_RETURN();
992
}
993
 
994
//}}}
995
//{{{  CdlPackagesDatabase:: get package information            
996
 
997
// ----------------------------------------------------------------------------
998
 
999
const std::vector<std::string>&
1000
CdlPackagesDatabaseBody::get_packages(void) const
1001
{
1002
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_packages");
1003
    CYG_REPORT_FUNCARG1XV(this);
1004
    CYG_PRECONDITION_THISC();
1005
 
1006
    CYG_REPORT_RETURN();
1007
    return package_names;
1008
}
1009
 
1010
bool
1011
CdlPackagesDatabaseBody::is_known_package(std::string name) const
1012
{
1013
    CYG_REPORT_FUNCNAMETYPE("CdlPackagesDatabase::is_known_package", "result %d");
1014
    CYG_REPORT_FUNCARG1XV(this);
1015
    CYG_PRECONDITION_THISC();
1016
 
1017
    bool result = false;
1018
    if (std::find(package_names.begin(), package_names.end(), name) != package_names.end()) {
1019
        result = true;
1020
    }
1021
 
1022
    CYG_REPORT_RETVAL(result);
1023
    return result;
1024
}
1025
 
1026
const std::string&
1027
CdlPackagesDatabaseBody::get_package_description(std::string pkg_name) const
1028
{
1029
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_package_description");
1030
    CYG_REPORT_FUNCARG1XV(this);
1031
    CYG_PRECONDITION_THISC();
1032
 
1033
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1034
    if (pkgs_i != packages.end()) {
1035
        CYG_REPORT_RETURN();
1036
        return pkgs_i->second.description;
1037
    }
1038
 
1039
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::get_package_description()");
1040
    static std::string dummy = "";
1041
    return dummy;
1042
}
1043
 
1044
const std::vector<std::string>&
1045
CdlPackagesDatabaseBody::get_package_aliases(std::string pkg_name) const
1046
{
1047
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_package_aliases");
1048
    CYG_REPORT_FUNCARG1XV(this);
1049
    CYG_PRECONDITION_THISC();
1050
 
1051
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1052
    if (pkgs_i != packages.end()) {
1053
        CYG_REPORT_RETURN();
1054
        return pkgs_i->second.aliases;
1055
    }
1056
 
1057
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::get_package_aliases()");
1058
    static std::vector<std::string> dummy;
1059
    return dummy;
1060
}
1061
 
1062
const std::vector<std::string>&
1063
CdlPackagesDatabaseBody::get_package_versions(std::string pkg_name) const
1064
{
1065
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_package_versions");
1066
    CYG_REPORT_FUNCARG1XV(this);
1067
    CYG_PRECONDITION_THISC();
1068
 
1069
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1070
    if (pkgs_i != packages.end()) {
1071
        CYG_REPORT_RETURN();
1072
        return pkgs_i->second.versions;
1073
    }
1074
 
1075
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::get_package_versions()");
1076
    static std::vector<std::string> dummy;
1077
    return dummy;
1078
}
1079
 
1080
const std::string&
1081
CdlPackagesDatabaseBody::get_package_directory(std::string pkg_name) const
1082
{
1083
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_package_directory");
1084
    CYG_REPORT_FUNCARG1XV(this);
1085
    CYG_PRECONDITION_THISC();
1086
 
1087
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1088
    if (pkgs_i != packages.end()) {
1089
        CYG_REPORT_RETURN();
1090
        return pkgs_i->second.directory;
1091
    }
1092
 
1093
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::get_package_directory()");
1094
    static std::string dummy = "";
1095
    return dummy;
1096
}
1097
 
1098
const std::string&
1099
CdlPackagesDatabaseBody::get_package_script(std::string pkg_name) const
1100
{
1101
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_package_script");
1102
    CYG_REPORT_FUNCARG1XV(this);
1103
    CYG_PRECONDITION_THISC();
1104
 
1105
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1106
    if (pkgs_i != packages.end()) {
1107
        CYG_REPORT_RETURN();
1108
        return pkgs_i->second.script;
1109
    }
1110
 
1111
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::get_package_script()");
1112
    static std::string dummy = "";
1113
    return dummy;
1114
}
1115
 
1116
bool
1117
CdlPackagesDatabaseBody::is_hardware_package(std::string pkg_name) const
1118
{
1119
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::is_hardware_package");
1120
    CYG_REPORT_FUNCARG1XV(this);
1121
    CYG_PRECONDITION_THISC();
1122
 
1123
    std::map<std::string,package_data>::const_iterator pkgs_i = packages.find(pkg_name);
1124
    if (pkgs_i != packages.end()) {
1125
        CYG_REPORT_RETURN();
1126
        return pkgs_i->second.hardware;
1127
    }
1128
 
1129
    CYG_FAIL("Invalid package name passed to CdlPackagesDatabase::is_hardware_package()");
1130
    return false;
1131
}
1132
 
1133
//}}}
1134
//{{{  CdlPackagesDatabase:: get target information             
1135
 
1136
// ----------------------------------------------------------------------------
1137
 
1138
const std::vector<std::string>&
1139
CdlPackagesDatabaseBody::get_targets(void) const
1140
{
1141
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_targets");
1142
    CYG_PRECONDITION_THISC();
1143
 
1144
    CYG_REPORT_RETURN();
1145
    return target_names;
1146
}
1147
 
1148
bool
1149
CdlPackagesDatabaseBody::is_known_target(std::string name) const
1150
{
1151
    CYG_REPORT_FUNCNAMETYPE("CdlPackagesDatabase::is_known_target", "result %d");
1152
    CYG_REPORT_FUNCARG1XV(this);
1153
    CYG_PRECONDITION_THISC();
1154
 
1155
    bool result = false;
1156
    if (std::find(target_names.begin(), target_names.end(), name) != target_names.end()) {
1157
        result = true;
1158
    }
1159
 
1160
    CYG_REPORT_RETVAL(result);
1161
    return result;
1162
}
1163
 
1164
const std::string&
1165
CdlPackagesDatabaseBody::get_target_description(std::string target_name) const
1166
{
1167
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_description");
1168
    CYG_PRECONDITION_THISC();
1169
 
1170
    std::map<std::string,target_data>::const_iterator target_i = targets.find(target_name);
1171
    if (target_i != targets.end()) {
1172
        CYG_REPORT_RETURN();
1173
        return target_i->second.description;
1174
    }
1175
 
1176
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_description()");
1177
    static std::string dummy = "";
1178
    return dummy;
1179
}
1180
 
1181
const std::vector<std::string>&
1182
CdlPackagesDatabaseBody::get_target_aliases(std::string target_name) const
1183
{
1184
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_aliases");
1185
    CYG_PRECONDITION_THISC();
1186
 
1187
    std::map<std::string,target_data>::const_iterator target_i = targets.find(target_name);
1188
    if (target_i != targets.end()) {
1189
        CYG_REPORT_RETURN();
1190
        return target_i->second.aliases;
1191
    }
1192
 
1193
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_aliases()");
1194
    static std::vector<std::string> dummy;
1195
    return dummy;
1196
}
1197
 
1198
const std::vector<std::string>&
1199
CdlPackagesDatabaseBody::get_target_packages(std::string target_name) const
1200
{
1201
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_packages");
1202
    CYG_PRECONDITION_THISC();
1203
 
1204
    std::map<std::string,target_data>::const_iterator target_i = targets.find(target_name);
1205
    if (target_i != targets.end()) {
1206
        CYG_REPORT_RETURN();
1207
        return target_i->second.packages;
1208
    }
1209
 
1210
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_packages()");
1211
    static std::vector<std::string> dummy;
1212
    return dummy;
1213
}
1214
 
1215
const std::vector<std::string>&
1216
CdlPackagesDatabaseBody::get_target_enables(std::string target_name) const
1217
{
1218
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_enables");
1219
    CYG_PRECONDITION_THISC();
1220
 
1221
    std::map<std::string,target_data>::const_iterator target_i = this->targets.find(target_name);
1222
    if (target_i != this->targets.end()) {
1223
        CYG_REPORT_RETURN();
1224
        return target_i->second.enable;
1225
    }
1226
 
1227
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_enables()");
1228
    static std::vector<std::string> dummy;
1229
    return dummy;
1230
}
1231
 
1232
const std::vector<std::string>&
1233
CdlPackagesDatabaseBody::get_target_disables(std::string target_name) const
1234
{
1235
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_disables");
1236
    CYG_PRECONDITION_THISC();
1237
 
1238
    std::map<std::string,target_data>::const_iterator target_i = this->targets.find(target_name);
1239
    if (target_i != this->targets.end()) {
1240
        CYG_REPORT_RETURN();
1241
        return target_i->second.disable;
1242
    }
1243
 
1244
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_disables()");
1245
    static std::vector<std::string> dummy;
1246
    return dummy;
1247
}
1248
 
1249
const std::vector<std::pair<std::string, std::string> >&
1250
CdlPackagesDatabaseBody::get_target_set_values(std::string target_name) const
1251
{
1252
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_target_set_values");
1253
    CYG_PRECONDITION_THISC();
1254
 
1255
    std::map<std::string,target_data>::const_iterator target_i = this->targets.find(target_name);
1256
    if (target_i != this->targets.end()) {
1257
        CYG_REPORT_RETURN();
1258
        return target_i->second.set_values;
1259
    }
1260
 
1261
    CYG_FAIL("Invalid target name passed to CdlPackagesDatabase::get_target_values()");
1262
    static std::vector<std::pair<std::string, std::string> > dummy;
1263
    return dummy;
1264
}
1265
 
1266
//}}}
1267
//{{{  CdlPackagesDatabase:: get template information           
1268
 
1269
// ----------------------------------------------------------------------------
1270
// Templates are different from packages and targets. The ecos.db file
1271
// does not contain all the information in one convenient file, instead
1272
// it is necessary to trawl through a templates sub-directory of the
1273
// component repository. There are no aliases. Descriptions can be obtained
1274
// only by executing the template file in a suitable interpreter.
1275
 
1276
const std::vector<std::string>&
1277
CdlPackagesDatabaseBody::get_templates(void) const
1278
{
1279
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_templates");
1280
    CYG_PRECONDITION_THISC();
1281
 
1282
    CYG_REPORT_RETURN();
1283
    return template_names;
1284
}
1285
 
1286
bool
1287
CdlPackagesDatabaseBody::is_known_template(std::string name) const
1288
{
1289
    CYG_REPORT_FUNCNAMETYPE("CdlPackagesDatabase::is_known_template", "result %d");
1290
    CYG_REPORT_FUNCARG1XV(this);
1291
    CYG_PRECONDITION_THISC();
1292
 
1293
    bool result = false;
1294
    if (std::find(template_names.begin(), template_names.end(), name) != template_names.end()) {
1295
        result = true;
1296
    }
1297
 
1298
    CYG_REPORT_RETVAL(result);
1299
    return result;
1300
}
1301
 
1302
const std::vector<std::string>&
1303
CdlPackagesDatabaseBody::get_template_versions(std::string template_name) const
1304
{
1305
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_template_versions");
1306
    CYG_REPORT_FUNCARG1XV(this);
1307
    CYG_PRECONDITION_THISC();
1308
 
1309
    std::map<std::string,template_data>::const_iterator template_i = templates.find(template_name);
1310
    if (template_i != templates.end()) {
1311
        CYG_REPORT_RETURN();
1312
        return template_i->second.versions;
1313
    }
1314
 
1315
    CYG_FAIL("Invalid template name passed to CdlPackagesDatabase::get_template_versions()");
1316
    static std::vector<std::string> dummy;
1317
    return dummy;
1318
}
1319
 
1320
std::string
1321
CdlPackagesDatabaseBody::get_template_filename(std::string template_name, std::string version_name) const
1322
{
1323
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_template_filename");
1324
    CYG_REPORT_FUNCARG1XV(this);
1325
    CYG_PRECONDITION_THISC();
1326
 
1327
    // Given the way templates are identified, the filename can be determined
1328
    // easily by concatenating a few strings. The only complication is that
1329
    // version_name may be an empty string, indicating that the most recent
1330
    // version should be used.
1331
    std::map<std::string,template_data>::const_iterator template_i = templates.find(template_name);
1332
    if (template_i == templates.end()) {
1333
        CYG_FAIL("Invalid template name passed to CdlPackagesDatabase::get_template_filename");
1334
        CYG_REPORT_RETURN();
1335
        return "";
1336
    }
1337
    if ("" == version_name) {
1338
        CYG_ASSERTC(0 != template_i->second.versions.size());
1339
        version_name = template_i->second.versions[0];
1340
    } else {
1341
        std::vector<std::string>::const_iterator vsn_i = std::find(template_i->second.versions.begin(),
1342
                                                                   template_i->second.versions.end(), version_name);
1343
        if (vsn_i == template_i->second.versions.end()) {
1344
            CYG_FAIL("Invalid template version passed to CdlPackagesDatabase::get_template_filename");
1345
            CYG_REPORT_RETURN();
1346
            return "";
1347
        }
1348
    }
1349
 
1350
    std::string result = component_repository + "/templates/" + template_name + "/" + version_name + ".ect";
1351
    CYG_REPORT_RETURN();
1352
    return result;
1353
}
1354
 
1355
// ----------------------------------------------------------------------------
1356
// The descriptions now live in an eCos savefile, i.e. a Tcl script, so
1357
// extracting them can be relatively expensive and needs to happen on
1358
// a just-in-time basis.
1359
 
1360
const std::string
1361
CdlPackagesDatabaseBody::get_template_description(std::string template_name, std::string version_name)
1362
{
1363
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_template_description");
1364
    CYG_REPORT_FUNCARG1XV(this);
1365
    CYG_PRECONDITION_THISC();
1366
 
1367
    // Is this a known template?
1368
    std::map<std::string, struct template_data>::iterator template_i = templates.find(template_name);
1369
    if (template_i == templates.end()) {
1370
        CYG_FAIL("Invalid template name passed to CdlPackagesDatabase::get_template_description");
1371
        CYG_REPORT_RETURN();
1372
        return "";
1373
    }
1374
 
1375
    // Is it a known version of the template?
1376
    if ("" == version_name) {
1377
        CYG_ASSERTC(0 != template_i->second.versions.size());
1378
        version_name = template_i->second.versions[0];
1379
    } else {
1380
        if (std::find(template_i->second.versions.begin(), template_i->second.versions.end(), version_name) ==
1381
            template_i->second.versions.end()) {
1382
 
1383
            CYG_FAIL("Invalid template version passed to CdlPackagesDatabase::get_template_description");
1384
            CYG_REPORT_RETURN();
1385
            return "";
1386
        }
1387
    }
1388
 
1389
    // We have a valid template and version. Has the version file in
1390
    // question been read in yet?
1391
    std::map<std::string, struct template_version_data>::iterator version_i;
1392
    version_i = template_i->second.version_details.find(version_name);
1393
    if (version_i != template_i->second.version_details.end()) {
1394
        CYG_REPORT_RETURN();
1395
        return version_i->second.description;
1396
    }
1397
 
1398
    std::string filename = this->get_template_filename(template_name, version_name);
1399
    if ("" == filename) {
1400
        CYG_REPORT_RETURN();
1401
        return "";
1402
    }
1403
    extract_template_details(filename, template_i->second.version_details[version_name].description,
1404
                             template_i->second.version_details[version_name].packages);
1405
    CYG_REPORT_RETURN();
1406
    return template_i->second.version_details[version_name].description;
1407
}
1408
 
1409
// ----------------------------------------------------------------------------
1410
// Similarly extracting package information needs to happen on a
1411
// just-in-time basis.
1412
const std::vector<std::string>&
1413
CdlPackagesDatabaseBody::get_template_packages(std::string template_name, std::string version_name)
1414
{
1415
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_template_packages");
1416
    CYG_REPORT_FUNCARG1XV(this);
1417
    CYG_PRECONDITION_THISC();
1418
 
1419
    static std::vector<std::string> dummy;
1420
 
1421
    // Is this a known template?
1422
    std::map<std::string, struct template_data>::iterator template_i = templates.find(template_name);
1423
    if (template_i == templates.end()) {
1424
        CYG_FAIL("Invalid template name passed to CdlPackagesDatabase::get_template_packages");
1425
        CYG_REPORT_RETURN();
1426
        return dummy;
1427
    }
1428
 
1429
    // Is it a known version of the template?
1430
    if ("" == version_name) {
1431
        CYG_ASSERTC(0 != template_i->second.versions.size());
1432
        version_name = template_i->second.versions[0];
1433
    } else {
1434
        if (std::find(template_i->second.versions.begin(), template_i->second.versions.end(), version_name) ==
1435
            template_i->second.versions.end()) {
1436
 
1437
            CYG_FAIL("Invalid template version passed to CdlPackagesDatabase::get_packages");
1438
            CYG_REPORT_RETURN();
1439
            return dummy;
1440
        }
1441
    }
1442
 
1443
    // We have a valid template and version. Has the version file in
1444
    // question been read in yet?
1445
    std::map<std::string, struct template_version_data>::iterator version_i;
1446
    version_i = template_i->second.version_details.find(version_name);
1447
    if (version_i != template_i->second.version_details.end()) {
1448
        CYG_REPORT_RETURN();
1449
        return version_i->second.packages;
1450
    }
1451
 
1452
    std::string filename = this->get_template_filename(template_name, version_name);
1453
    if ("" == filename) {
1454
        CYG_REPORT_RETURN();
1455
        return dummy;
1456
    }
1457
    extract_template_details(filename, template_i->second.version_details[version_name].description,
1458
                             template_i->second.version_details[version_name].packages);
1459
    CYG_REPORT_RETURN();
1460
    return template_i->second.version_details[version_name].packages;
1461
}
1462
 
1463
// ----------------------------------------------------------------------------
1464
// Extracting the description and package information involves running
1465
// the script through a Tcl interpreter extended with the appropriate
1466
// commands. Most of the savefile information is irrelevant and is handled
1467
// by extract_ignore(). The commands of interest are cdl_configuration and
1468
// its sub-commands description and package.
1469
 
1470
static int
1471
extract_ignore(CdlInterpreter interp, int argc, const char* argv[])
1472
{
1473
    return TCL_OK;
1474
}
1475
 
1476
static int
1477
extract_cdl_configuration(CdlInterpreter interp, int argc, const char* argv[])
1478
{
1479
    CYG_REPORT_FUNCNAMETYPE("extract_cdl_configuration", "result %d");
1480
    CYG_REPORT_FUNCARG2XV(interp, argc);
1481
    CYG_PRECONDITION_CLASSC(interp);
1482
 
1483
    int result = TCL_OK;
1484
 
1485
    // usage: cdl_configuration <name> <body>
1486
    if (3 != argc) {
1487
        interp->set_result("Invalid cdl_configuration command in template, expecting two arguments");
1488
        result = TCL_ERROR;
1489
    } else {
1490
        // Ignore the first argument for now.
1491
        std::string tmp;
1492
        result = interp->eval(argv[2], tmp);
1493
 
1494
        // After processing the cdl_configuration command the description and
1495
        // package information should be known. There is no point in processing
1496
        // the rest of the file.
1497
        if (TCL_OK == result) {
1498
            interp->set_result("OK");
1499
            result = TCL_ERROR;
1500
        }
1501
    }
1502
 
1503
    CYG_REPORT_RETVAL(result);
1504
    return result;
1505
}
1506
 
1507
static int
1508
extract_cdl_description(CdlInterpreter interp, int argc, const char* argv[])
1509
{
1510
    CYG_REPORT_FUNCNAMETYPE("extract_cdl_description", "result %d");
1511
    CYG_REPORT_FUNCARG2XV(interp, argc);
1512
    CYG_PRECONDITION_CLASSC(interp);
1513
 
1514
    int result = TCL_OK;
1515
 
1516
    // usage: package <name>
1517
    if (2 != argc) {
1518
        interp->set_result("Invalid description command in template, expecting just one argument");
1519
        result = TCL_ERROR;
1520
    } else {
1521
        ClientData client_data = interp->get_assoc_data(template_description_key);
1522
        CYG_ASSERTC(0 != client_data);
1523
        std::string* result_ptr = static_cast<std::string*>(client_data);
1524
        *result_ptr = argv[1];
1525
    }
1526
 
1527
    CYG_REPORT_RETVAL(result);
1528
    return result;
1529
}
1530
 
1531
static int
1532
extract_cdl_package(CdlInterpreter interp, int argc, const char* argv[])
1533
{
1534
    CYG_REPORT_FUNCNAMETYPE("extract_cdl_package", "result %d");
1535
    CYG_REPORT_FUNCARG2XV(interp, argc);
1536
    CYG_PRECONDITION_CLASSC(interp);
1537
 
1538
    int result = TCL_OK;
1539
 
1540
    // usage: package <name> <version>
1541
    if (2 > argc) {
1542
        interp->set_result("Invalid package command in template, expecting two arguments");
1543
        result = TCL_ERROR;
1544
    } else {
1545
        ClientData client_data = interp->get_assoc_data(template_packages_key);
1546
        CYG_ASSERTC(0 != client_data);
1547
        std::vector<std::string>* result_ptr = static_cast<std::vector<std::string>*>(client_data);
1548
        result_ptr->push_back(argv[1]);
1549
    }
1550
    CYG_REPORT_RETVAL(result);
1551
    return result;
1552
}
1553
 
1554
 
1555
void
1556
CdlPackagesDatabaseBody::extract_template_details(std::string filename, std::string& description,
1557
                                                      std::vector<std::string>& packages)
1558
{
1559
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::extract_template_description");
1560
 
1561
    CdlInterpreter interp = CdlInterpreterBody::make();
1562
    interp->set_assoc_data(template_description_key, static_cast<ClientData>(&description));
1563
    interp->set_assoc_data(template_packages_key,    static_cast<ClientData>(&packages));
1564
    static CdlInterpreterCommandEntry extract_commands[] =
1565
    {
1566
        CdlInterpreterCommandEntry("cdl_savefile_version",  &extract_ignore                 ),
1567
        CdlInterpreterCommandEntry("cdl_savefile_command",  &extract_ignore                 ),
1568
        CdlInterpreterCommandEntry("cdl_configuration",     &extract_cdl_configuration      ),
1569
        CdlInterpreterCommandEntry("hardware",              &extract_ignore                 ),
1570
        CdlInterpreterCommandEntry("template",              &extract_ignore                 ),
1571
        CdlInterpreterCommandEntry("description",           &extract_cdl_description        ),
1572
        CdlInterpreterCommandEntry("package",               &extract_cdl_package            ),
1573
        CdlInterpreterCommandEntry("unknown",               &extract_ignore                 ),
1574
        CdlInterpreterCommandEntry("",                      0                               )
1575
    };
1576
    std::vector<CdlInterpreterCommandEntry> new_commands;
1577
    for (int i = 0; 0 != extract_commands[i].command; i++) {
1578
        new_commands.push_back(extract_commands[i]);
1579
    }
1580
    interp->push_commands(new_commands);
1581
 
1582
    std::string tmp;
1583
    int result = interp->eval_file(filename, tmp);
1584
    // Special escape mechanism, see extract_cdl_configuration() above
1585
    if ((TCL_ERROR == result) && ("OK" == tmp)) {
1586
        result = TCL_OK;
1587
    }
1588
#if 0    
1589
    if (TCL_OK != result) {
1590
        // No obvious way of recovering just yet
1591
    }
1592
#endif
1593
    delete interp;
1594
 
1595
    CYG_REPORT_RETURN();
1596
}
1597
 
1598
//}}}
1599
//{{{  CdlPackagesDatabase:: get_valid_cflags()                 
1600
 
1601
// ----------------------------------------------------------------------------
1602
 
1603
const std::vector<std::string>&
1604
CdlPackagesDatabaseBody::get_valid_cflags()
1605
{
1606
    CYG_REPORT_FUNCNAME("CdlPackagesDatabase::get_valid_compiler_flags");
1607
 
1608
    static std::vector<std::string> result_vec;
1609
    static const char* valid_flags[] = {
1610
        "ARCHFLAGS",  "CARCHFLAGS",  "CXXARCHFLAGS",  "LDARCHFLAGS",
1611
        "ERRFLAGS",   "CERRFLAGS",   "CXXERRFLAGS",   "LDERRFLAGS",
1612
        "LANGFLAGS",  "CLANGFLAGS",  "CXXLANGFLAGS",  "LDLANGFLAGS",
1613
        "DBGFLAGS",   "CDBGFLAGS",   "CXXDBGFLAGS",   "LDDBGFLAGS",
1614
        "EXTRAFLAGS", "CEXTRAFLAGS", "CXXEXTRAFLAGS", "LDEXTRAFLAGS",
1615
 
1616
    };
1617
 
1618
    if (0 == result_vec.size()) {
1619
        for (int i = 0; 0 != valid_flags[i]; i++) {
1620
            result_vec.push_back(valid_flags[i]);
1621
        }
1622
    }
1623
    CYG_REPORT_RETURN();
1624
    return result_vec;
1625
}
1626
 
1627
//}}}

powered by: WebSVN 2.1.0

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