comparison host/libcdl/database.cxx @ 76:435cced73e2f ecos-v1_3_1-release

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