5 //============================================================================
9 // This header file declares the classes related to software
12 //============================================================================
13 //####COPYRIGHTBEGIN####
15 // ----------------------------------------------------------------------------
16 // Copyright (C) 2002 Bart Veer
17 // Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
19 // This file is part of the eCos host tools.
21 // This program is free software; you can redistribute it and/or modify it
22 // under the terms of the GNU General Public License as published by the Free
23 // Software Foundation; either version 2 of the License, or (at your option)
26 // This program is distributed in the hope that it will be useful, but WITHOUT
27 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
31 // You should have received a copy of the GNU General Public License along with
32 // this program; if not, write to the Free Software Foundation, Inc.,
33 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 // ----------------------------------------------------------------------------
37 //####COPYRIGHTEND####
38 //============================================================================
39 //#####DESCRIPTIONBEGIN####
45 // Requires: cdlcore.hxx
46 // Usage: #include <cdl.hxx>
48 //####DESCRIPTIONEND####
49 //============================================================================
52 //{{{ nested #include's
54 // ----------------------------------------------------------------------------
55 // Software CDL depends on the core but adds no new system requirements.
58 # include <cdlcore.hxx>
63 //{{{ Forward declarations of the body classes
65 // ----------------------------------------------------------------------------
66 // This section provides forward declarations of the main classes used
67 // for software configuration.
69 class CdlConfigurationBody;
71 class CdlComponentBody;
73 class CdlPackagesDatabaseBody;
75 typedef CdlConfigurationBody* CdlConfiguration;
76 typedef CdlPackageBody* CdlPackage;
77 typedef CdlComponentBody* CdlComponent;
78 typedef CdlOptionBody* CdlOption;
79 typedef CdlPackagesDatabaseBody* CdlPackagesDatabase;
81 typedef const CdlConfigurationBody* CdlConstConfiguration;
82 typedef const CdlPackageBody* CdlConstPackage;
83 typedef const CdlComponentBody* CdlConstComponent;
84 typedef const CdlOptionBody* CdlConstOption;
85 typedef const CdlPackagesDatabaseBody* CdlConstPackagesDatabase;
88 //{{{ CdlPackagesDatabase class
90 // ----------------------------------------------------------------------------
91 // An eCos component repository can get to be quite complicated. There will
92 // be a number of core packages supplied by Red Hat. There may also be some
93 // number of third party and unsupported packages. Each package may come in
94 // several different versions. Keeping track of everything that has been
95 // installed should involve a separate administration tool, and there should
96 // be some sort of database of all this information.
98 // At the time of writing there is no such administration tool and there is
99 // no database with details of the various packages. Instead there is a
100 // static file "packages" at the top level of the component repository,
101 // containing some of the desired information.
103 // For now a temporary CdlPackagesDatabase class is provided.
104 // Essentially this provides C++ access to the packages file. In the
105 // long term this class will be replaced completely by a full and more
106 // rational implementation.
108 // The packages database class also, temporarily, provides information about
109 // targets and templates. This will change in future. A target will be specified
110 // by a save file, the output from Hardy. A template will also be specified by
111 // a save file, a partial software configuration.
113 class CdlPackagesDatabaseBody {
115 friend class CdlTest;
116 friend class CdlDbParser;
120 static CdlPackagesDatabase make(std::string = "", CdlDiagnosticFnPtr /* error */ = 0,
121 CdlDiagnosticFnPtr /* warn */ = 0);
123 ~CdlPackagesDatabaseBody();
125 std::string get_component_repository() const;
127 const std::vector<std::string>& get_packages(void) const;
128 bool is_known_package(std::string) const;
129 const std::string& get_package_description(std::string) const;
130 const std::vector<std::string>& get_package_aliases(std::string) const;
131 const std::vector<std::string>& get_package_versions(std::string) const;
132 const std::string& get_package_directory(std::string) const;
133 const std::string& get_package_script(std::string) const;
134 bool is_hardware_package(std::string) const;
136 const std::vector<std::string>& get_targets(void) const;
137 bool is_known_target(std::string) const;
138 const std::string& get_target_description(std::string) const;
139 const std::vector<std::string>& get_target_aliases(std::string) const;
140 const std::vector<std::string>& get_target_packages(std::string) const;
141 const std::vector<std::string>& get_target_enables(std::string) const;
142 const std::vector<std::string>& get_target_disables(std::string) const;
143 const std::vector<std::pair<std::string,std::string> >& get_target_set_values(std::string) const;
145 const std::vector<std::string>& get_templates(void) const;
146 bool is_known_template(std::string) const;
147 std::string get_template_filename(std::string, std::string = "") const;
148 const std::vector<std::string>& get_template_versions(std::string) const;
149 const std::string get_template_description(std::string, std::string = "");
150 const std::vector<std::string>& get_template_packages(std::string, std::string = "");
151 static void extract_template_details(std::string /* filename */, std::string& /* description */,
152 std::vector<std::string>& /* packages */);
154 // What are the valid compiler flag variables (ARCHFLAGS, ERRFLAGS, ...)?
155 // For now the library provides a static vector of these things, but
156 // this area is likely to change in future
157 static const std::vector<std::string>& get_valid_cflags();
159 // Control verbosity when reading in a database
160 static void set_verbose(bool);
162 bool check_this(cyg_assert_class_zeal = cyg_quick) const;
163 CYGDBG_DECLARE_MEMLEAK_COUNTER();
166 // The only valid constructor gets invoked from the make() member function.
167 // The argument should be a pathname for the component repository. The
168 // constructor is responsible for reading in the whole packages file.
169 CdlPackagesDatabaseBody(std::string, CdlDiagnosticFnPtr, CdlDiagnosticFnPtr);
171 std::string component_repository;
172 std::vector<std::string> package_names;
173 struct package_data {
175 std::string description;
176 std::vector<std::string> aliases;
177 std::vector<std::string> versions;
178 std::string directory;
182 std::map<std::string,struct package_data> packages;
184 std::vector<std::string> target_names;
187 std::string description;
188 std::vector<std::string> aliases;
189 std::vector<std::string> packages;
190 std::vector<std::string> enable;
191 std::vector<std::string> disable;
192 std::vector<std::pair<std::string, std::string> > set_values;
194 std::map<std::string, struct target_data> targets;
196 std::vector<std::string> template_names;
197 struct template_version_data {
199 std::string description;
200 std::vector<std::string> packages;
202 struct template_data {
204 std::vector<std::string> versions;
205 std::map<std::string, struct template_version_data> version_details;
207 std::map<std::string, struct template_data> templates;
210 CdlPackagesDatabaseBody_Invalid = 0,
211 CdlPackagesDatabaseBody_Magic = 0x50896acb
212 } cdlpackagesdatabasebody_cookie;
214 // This allows test cases to overwrite the name of the file
215 // containing the database information.
216 static char* database_name;
218 // Control whether or not minor problems with the database should be
220 static bool verbose_mode;
222 // The default constructor, copy constructor and assignment operator are illegal.
223 CdlPackagesDatabaseBody();
224 CdlPackagesDatabaseBody(const CdlPackagesDatabaseBody&);
225 CdlPackagesDatabaseBody& operator=(const CdlPackagesDatabaseBody&);
230 //{{{ CdlConfiguration class
232 // ----------------------------------------------------------------------------
233 // The CdlConfiguration class is the toplevel used for mainpulating
234 // software configurations. It consists of a number of loaded packages,
235 // each of which consists of some hierarchy of components and options,
236 // plus dialogs, wizards, and interfaces from the core.
238 // Typically an application will deal with only one configuration at a
239 // time. There will be exceptions. The most obvious example would be
240 // some sort of diff utility, but there may well be times when a user
241 // wants to edit multiple configurations. One example would be a board
242 // containing two separate processors, e.g. a conventional one coupled
243 // with a separate DSP, and eCos is supposed to run on both: the two
244 // chips will need to interact, and hence there may well be
245 // configurability dependencies between them.
247 // A configuration object does not exist in isolation. It must be tied
248 // to an eCos component repository via a database objects. It must
249 // also be supplied with a suitable Tcl interpreter.
251 class CdlConfigurationBody : public virtual CdlToplevelBody
253 friend class CdlTest;
257 // ----------------------------------------------------------------------------
258 // Create a new configuration.
259 // Currently this requires a name, a database and a master interpreter.
260 // The name is not used very much, but does appear in savefiles.
261 // The packages database and the interpreter must be created before
262 // any configuration object.
263 static CdlConfiguration make(std::string /* name */, CdlPackagesDatabase, CdlInterpreter);
264 CdlPackagesDatabase get_database() const;
266 // Loading and unloading packages. This can happen in a number
267 // of different ways:
269 // 1) explicitly adding or removing a single package
270 // 2) changing the version of a package, which means unloading
271 // the old version and reloading the new one. Generally
272 // user settings should be preserved where possible.
273 // 3) loading in a full or minimal savefile. The library
274 // does not actually distinguish between the two when
275 // loading, only when saving.
276 // 4) adding a full or minimal savefile.
277 // 5) setting a template for the first time. This is much the
278 // same as adding a minimal savefile. However the library
279 // keeps track of the "current" template and only one
280 // can be loaded at a time. The library does not keep
281 // track of which savefile(s) have been added.
282 // 6) changing a template. This means unloading the packages
283 // that were loaded for the old template, then loading in
285 // 7) unsetting the template. This just involves an unload.
286 // 8) setting the hardware. Currently the database defines
287 // each supported target, listing the packages that should
288 // be loaded and possibly some option details. This is
289 // subject to change in future.
290 // 9) changing the hardware. This is much the same as changing
292 // 10) unsetting the hardware.
294 // The unload operations are comparatively safe, although
295 // they can result in new conflicts and the user may well want
296 // to cancel the operation after discovering how many new
297 // problems there would be. The load operations are a bit more
298 // dangerous since they depend on external data and hence can
299 // fail for a variety of reasons: missing files, corrupt files,
300 // clashes with existing data, ... Changing e.g. a template
301 // is especially dangerous because of the number of things
302 // that can go wrong. All of these operations need to happen
303 // in a transaction which the user can cancel. There are two
304 // versions of all the relevant routines, one which operates
305 // in an existing transaction and one which creates a new
308 // Any operation that involves loading CDL data takes two
309 // CdlDiagnosticFnPtr arguments, one for errors and one for
310 // warnings. These should report the message to the user by
311 // some suitable means. The error fnptr may throw a
312 // CdlParseException to abort the current load immediately,
313 // otherwise the load operation will be aborted at the end
314 // if any errors were detected. New conflicts are not
315 // handled by these diagnostic functions, instead they
316 // are handled by the normal transaction methods.
318 // A version argument of "" implies the most recent version.
319 void load_package(std::string /* name */, std::string /* version */,
320 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
321 void load_package(CdlTransaction, std::string /* name */, std::string /* version */,
322 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
324 void unload_package(std::string /* name */, bool /* limbo */ = true);
325 void unload_package(CdlPackage, bool /* limbo */ = true);
326 void unload_package(CdlTransaction, std::string /* name */, bool /* limbo */ = true);
327 void unload_package(CdlTransaction, CdlPackage, bool /* limbo */ = true);
329 void change_package_version(std::string /*name*/, std::string /*version*/,
330 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
331 void change_package_version(CdlPackage, std::string /*version*/, CdlDiagnosticFnPtr /* error */,
332 CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
334 void change_package_version(CdlTransaction, std::string /*name*/, std::string /*version*/,
335 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
336 void change_package_version(CdlTransaction, CdlPackage, std::string /*version*/, CdlDiagnosticFnPtr /* error */,
337 CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
339 // Loading a savefile is different in that it creates a new
340 // toplevel. Since transactions can only be created if the
341 // toplevel already exists, it is not possible to have a
342 // per-transaction load() operation. It is possible to have
343 // a per-transaction add() operation.
344 static CdlConfiguration load(std::string /* filename */, CdlPackagesDatabase, CdlInterpreter,
345 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */);
347 void add(std::string /* filename */,
348 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */);
349 void add(CdlTransaction, std::string /* filename */,
350 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */);
352 // As with packages, a version of "" implies the most recent.
353 void set_template(std::string, std::string /* version */,
354 CdlDiagnosticFnPtr, CdlDiagnosticFnPtr /* warn */,bool /* limbo */ = true);
355 void set_template_file(std::string,
356 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
357 void set_template(CdlTransaction, std::string, std::string /* version */,
358 CdlDiagnosticFnPtr, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
359 void set_template_file(CdlTransaction, std::string,
360 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
361 void unload_template(bool /* limbo */ = true);
362 void unload_template(CdlTransaction, bool /* limbo */ = true);
363 std::string get_template() const;
364 void set_template_name(std::string); // Intended for library use only
366 void set_hardware(std::string,
367 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
368 void set_hardware(CdlTransaction, std::string,
369 CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true);
370 void unload_hardware(bool /* limbo */ = true);
371 void unload_hardware(CdlTransaction, bool /* limbo */ = true);
372 std::string get_hardware() const;
373 void set_hardware_name(std::string); // Intended for library use only
375 // ----------------------------------------------------------------------------
376 // Save a configuration to a file
377 void save(std::string, bool /* minimal */ = false);
378 void initialize_savefile_support();
379 std::string get_save_file() const;
381 // ----------------------------------------------------------------------------
382 // Get rid of a configuration.
383 ~CdlConfigurationBody();
385 virtual std::string get_class_name() const;
386 bool check_this(cyg_assert_class_zeal = cyg_quick) const;
387 CYGDBG_DECLARE_MEMLEAK_COUNTER();
391 // The only legal constructor, invoked from make() and load()
392 CdlConfigurationBody(std::string, CdlPackagesDatabase, CdlInterpreter);
394 // The internal implementation of the persistence support
395 virtual void save(CdlInterpreter, Tcl_Channel, int, bool);
396 static int savefile_configuration_command(CdlInterpreter, int, const char*[]);
397 static int savefile_description_command(CdlInterpreter, int, const char*[]);
398 static int savefile_hardware_command(CdlInterpreter, int, const char*[]);
399 static int savefile_template_command(CdlInterpreter, int, const char*[]);
400 static int savefile_package_command(CdlInterpreter, int, const char*[]);
402 std::string current_hardware;
403 std::string current_template;
404 std::string description;
405 CdlPackagesDatabase database;
406 std::string save_file;
408 CdlConfigurationBody_Invalid = 0,
409 CdlConfigurationBody_Magic = 0x5c409a3d
410 } cdlconfigurationbody_cookie;
412 // The constructor can only be invoked via the make() and load()
413 // members. Other constructors and the assignment operator are
415 CdlConfigurationBody();
416 CdlConfigurationBody(const CdlConfigurationBody&);
417 CdlConfigurationBody& operator=(const CdlConfigurationBody&);
422 //{{{ CdlPackage class
424 // ----------------------------------------------------------------------------
425 // Packages inherit from most of the base classes.
427 class CdlPackageBody : public virtual CdlNodeBody,
428 public virtual CdlContainerBody,
429 public virtual CdlUserVisibleBody,
430 public virtual CdlValuableBody,
431 public virtual CdlParentableBody,
432 public virtual CdlBuildableBody,
433 public virtual CdlDefinableBody,
434 public virtual CdlLoadableBody,
435 public virtual CdlBuildLoadableBody,
436 public virtual CdlDefineLoadableBody
438 friend class CdlTest;
440 // Packages should not be created by application code, but
441 // the CdlConfiguration class must be able to do so inside
443 friend class CdlConfigurationBody;
449 static int parse_package(CdlInterpreter, int, const char*[]);
450 static int parse_hardware(CdlInterpreter, int, const char*[]);
451 static int parse_install_proc(CdlInterpreter, int, const char*[]);
452 static int parse_license_proc(CdlInterpreter, int, const char*[]);
454 // Override the CdlDefineLoadable member. Hardware packages always
455 // send their configuration options to hardware.h
456 virtual std::string get_config_header() const;
458 bool is_hardware_package() const;
459 bool has_install_proc() const;
460 const cdl_tcl_code& get_install_proc() const;
461 bool has_license_proc() const;
462 const cdl_tcl_code& get_license_proc() const;
464 // Propagation support. Because of multiple virtual inheritance
465 // it is necessary to invoke the container and valuable
467 virtual void update(CdlTransaction, CdlUpdate);
469 // Persistence support.
470 virtual void save(CdlInterpreter, Tcl_Channel, int, bool);
471 static void initialize_savefile_support(CdlToplevel);
472 static int savefile_package_command(CdlInterpreter, int, const char*[]);
474 // Was this package loaded because of a template or hardware setting?
475 bool belongs_to_template() const;
476 bool belongs_to_hardware() const;
478 virtual std::string get_class_name() const;
479 bool check_this(cyg_assert_class_zeal = cyg_quick) const;
480 CYGDBG_DECLARE_MEMLEAK_COUNTER();
484 // The only valid constructor requires a number of fields
485 CdlPackageBody(std::string /* name */, CdlConfiguration, std::string /* directory */);
487 // Other constructors are illegal
489 CdlPackageBody(const CdlPackageBody&);
490 CdlPackageBody& operator=(const CdlPackageBody&);
492 bool loaded_for_template;
493 bool loaded_for_hardware;
496 CdlPackageBody_Invalid = 0,
497 CdlPackageBody_Magic = 0x1d7c0d43
498 } cdlpackagebody_cookie;
502 //{{{ CdlComponent class
504 // ----------------------------------------------------------------------------
505 // Similarly components just inherit from the appropriate base classes.
507 class CdlComponentBody : public virtual CdlNodeBody,
508 public virtual CdlContainerBody,
509 public virtual CdlUserVisibleBody,
510 public virtual CdlValuableBody,
511 public virtual CdlParentableBody,
512 public virtual CdlBuildableBody,
513 public virtual CdlDefinableBody
515 friend class CdlTest;
520 static int parse_component(CdlInterpreter, int, const char*[]);
521 static int parse_script(CdlInterpreter, int, const char*[]);
523 // Propagation support. Because of multiple virtual inheritance
524 // it is necessary to invoke the container and valuable
526 virtual void update(CdlTransaction, CdlUpdate);
528 // Persistence support.
529 virtual void save(CdlInterpreter, Tcl_Channel, int, bool);
530 static void initialize_savefile_support(CdlToplevel);
531 static int savefile_component_command(CdlInterpreter, int, const char*[]);
533 virtual std::string get_class_name() const;
534 bool check_this(cyg_assert_class_zeal = cyg_quick) const;
535 CYGDBG_DECLARE_MEMLEAK_COUNTER();
539 // The only valid constructor requires a name.
540 CdlComponentBody(std::string);
543 CdlComponentBody_Invalid = 0,
544 CdlComponentBody_Magic = 0x6359d9a7
545 } cdlcomponentbody_cookie;
547 // Other constructors are illegal
549 CdlComponentBody(const CdlComponentBody&);
550 CdlComponentBody& operator=(const CdlComponentBody&);
554 //{{{ CdlOption class
556 // ----------------------------------------------------------------------------
557 // Again options just inherit their functionality from the base classes.
559 class CdlOptionBody : public virtual CdlNodeBody,
560 public virtual CdlUserVisibleBody,
561 public virtual CdlValuableBody,
562 public virtual CdlParentableBody,
563 public virtual CdlBuildableBody,
564 public virtual CdlDefinableBody
566 friend class CdlTest;
571 static int parse_option(CdlInterpreter, int, const char*[]);
573 // Persistence support.
574 virtual void save(CdlInterpreter, Tcl_Channel, int, bool);
575 static void initialize_savefile_support(CdlToplevel);
576 static int savefile_option_command(CdlInterpreter, int, const char*[]);
578 virtual std::string get_class_name() const;
579 bool check_this(cyg_assert_class_zeal = cyg_quick) const;
580 CYGDBG_DECLARE_MEMLEAK_COUNTER();
583 CdlOptionBody(std::string);
586 CdlOptionBody_Invalid = 0,
587 CdlOptionBody_Magic = 0x1c1162d1
588 } cdloptionbody_cookie;
591 CdlOptionBody(const CdlOptionBody&);
592 CdlOptionBody& operator=(const CdlOptionBody&);
597 #endif /* !__CDL_HXX */