Mercurial > flash_v2
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 //}}} |
