unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / tools / src / libcdl / cdl.hxx
1 #ifndef __CDL_HXX
2 # define __CDL_HXX
3 //{{{  Banner                                   
4
5 //============================================================================
6 //
7 //      cdl.hxx
8 //
9 //      This header file declares the classes related to software
10 //      configuration.
11 //
12 //============================================================================
13 //####COPYRIGHTBEGIN####
14 //                                                                          
15 // ----------------------------------------------------------------------------
16 // Copyright (C) 2002 Bart Veer
17 // Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
18 //
19 // This file is part of the eCos host tools.
20 //
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) 
24 // any later version.
25 // 
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 
29 // more details.
30 // 
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.
34 //
35 // ----------------------------------------------------------------------------
36 //                                                                          
37 //####COPYRIGHTEND####
38 //============================================================================
39 //#####DESCRIPTIONBEGIN####
40 //
41 // Author(s):   bartv
42 // Contact(s):  bartv
43 // Date:        1998/02/09
44 // Version:     0.02
45 // Requires:    cdlcore.hxx
46 // Usage:       #include <cdl.hxx>
47 //
48 //####DESCRIPTIONEND####
49 //============================================================================
50
51 //}}}
52 //{{{  nested #include's                        
53
54 // ----------------------------------------------------------------------------
55 // Software CDL depends on the core but adds no new system requirements.
56
57 #ifndef __CDLCORE_HXX
58 # include <cdlcore.hxx>
59 #endif
60
61 //}}}
62
63 //{{{  Forward declarations of the body classes 
64
65 // ----------------------------------------------------------------------------
66 // This section provides forward declarations of the main classes used
67 // for software configuration.
68
69 class CdlConfigurationBody;
70 class CdlPackageBody;
71 class CdlComponentBody;
72 class CdlOptionBody;
73 class CdlPackagesDatabaseBody;
74
75 typedef CdlConfigurationBody*           CdlConfiguration;
76 typedef CdlPackageBody*                 CdlPackage;
77 typedef CdlComponentBody*               CdlComponent;
78 typedef CdlOptionBody*                  CdlOption;
79 typedef CdlPackagesDatabaseBody*        CdlPackagesDatabase;
80
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;
86
87 //}}}
88 //{{{  CdlPackagesDatabase class                
89
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.
97 //
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.
102 //
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.
107 //
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.
112
113 class CdlPackagesDatabaseBody {
114
115     friend class CdlTest;
116     friend class CdlDbParser;
117     
118   public:
119
120     static CdlPackagesDatabase  make(std::string = "", CdlDiagnosticFnPtr /* error */ = 0,
121                                      CdlDiagnosticFnPtr /* warn */ = 0);
122     bool                        update(void);
123     ~CdlPackagesDatabaseBody();
124
125     std::string                         get_component_repository() const;
126     
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;
135
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;
144     
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 */);
153     
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();
158
159     // Control verbosity when reading in a database
160     static void set_verbose(bool);
161     
162     bool check_this(cyg_assert_class_zeal = cyg_quick) const;
163     CYGDBG_DECLARE_MEMLEAK_COUNTER();
164     
165   private:
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);
170
171     std::string                         component_repository;
172     std::vector<std::string>            package_names;
173     struct package_data {
174       public:
175         std::string                     description;
176         std::vector<std::string>        aliases;
177         std::vector<std::string>        versions;
178         std::string                     directory;
179         std::string                     script;
180         bool                            hardware;
181     };
182     std::map<std::string,struct package_data> packages;
183     
184     std::vector<std::string>            target_names;
185     struct target_data {
186       public:
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;
193     };
194     std::map<std::string, struct target_data>    targets;
195     
196     std::vector<std::string>            template_names;
197     struct template_version_data {
198       public:
199         std::string                     description;
200         std::vector<std::string>        packages;
201     };
202     struct template_data {
203       public:
204         std::vector<std::string>        versions;
205         std::map<std::string, struct template_version_data> version_details;
206     };
207     std::map<std::string, struct template_data>   templates;
208     
209     enum {
210         CdlPackagesDatabaseBody_Invalid = 0,
211         CdlPackagesDatabaseBody_Magic   = 0x50896acb
212     } cdlpackagesdatabasebody_cookie;
213
214     // This allows test cases to overwrite the name of the file
215     // containing the database information.
216     static char* database_name;
217
218     // Control whether or not minor problems with the database should be
219     // reported.
220     static bool verbose_mode;
221     
222     // The default constructor, copy constructor and assignment operator are illegal.
223     CdlPackagesDatabaseBody();
224     CdlPackagesDatabaseBody(const CdlPackagesDatabaseBody&);
225     CdlPackagesDatabaseBody& operator=(const CdlPackagesDatabaseBody&);
226     
227 };
228
229 //}}}
230 //{{{  CdlConfiguration class                   
231
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.
237 //
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.
246 //
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.
250
251 class CdlConfigurationBody : public virtual CdlToplevelBody
252 {
253     friend class CdlTest;
254
255   public:
256     
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;
265
266     // Loading and unloading packages. This can happen in a number
267     // of different ways:
268     //
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
284     //    the new one.
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
291     //    the template.
292     // 10) unsetting the hardware.
293     //
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
306     // one.
307     //
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.
317
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);
323
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);
328     
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);
333
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);
338
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 */);
346
347     void add(std::string /* filename */,
348              CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */);
349     void add(CdlTransaction, std::string /* filename */,
350              CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */);
351
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
365
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
374     
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;
380
381     // ----------------------------------------------------------------------------
382     // Get rid of a configuration.
383     ~CdlConfigurationBody();
384
385     virtual std::string         get_class_name() const;
386     bool                        check_this(cyg_assert_class_zeal = cyg_quick) const;
387     CYGDBG_DECLARE_MEMLEAK_COUNTER();
388     
389   private:
390
391     // The only legal constructor, invoked from make() and load()
392     CdlConfigurationBody(std::string, CdlPackagesDatabase, CdlInterpreter);
393
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*[]);
401     
402     std::string                 current_hardware;
403     std::string                 current_template;
404     std::string                 description;
405     CdlPackagesDatabase         database;
406     std::string                 save_file;
407     enum {
408         CdlConfigurationBody_Invalid    = 0,
409         CdlConfigurationBody_Magic      = 0x5c409a3d
410     } cdlconfigurationbody_cookie;
411
412     // The constructor can only be invoked via the make() and load()
413     // members. Other constructors and the assignment operator are
414     // illegal.
415     CdlConfigurationBody();
416     CdlConfigurationBody(const CdlConfigurationBody&);
417     CdlConfigurationBody& operator=(const CdlConfigurationBody&);
418     
419 };
420
421 //}}}
422 //{{{  CdlPackage class                         
423
424 // ----------------------------------------------------------------------------
425 // Packages inherit from most of the base classes.
426
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
437 {                       
438     friend class CdlTest;
439
440     // Packages should not be created by application code, but
441     // the CdlConfiguration class must be able to do so inside
442     // load_package();
443     friend class CdlConfigurationBody;
444     
445   public:
446
447     ~CdlPackageBody();
448     
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*[]);
453
454     // Override the CdlDefineLoadable member. Hardware packages always
455     // send their configuration options to hardware.h
456     virtual std::string get_config_header() const;
457     
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;
463
464     // Propagation support. Because of multiple virtual inheritance
465     // it is necessary to invoke the container and valuable
466     // update members.
467     virtual void update(CdlTransaction, CdlUpdate);
468     
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*[]);
473
474     // Was this package loaded because of a template or hardware setting?
475     bool                belongs_to_template() const;
476     bool                belongs_to_hardware() const;
477     
478     virtual std::string get_class_name() const;
479     bool                check_this(cyg_assert_class_zeal = cyg_quick) const;
480     CYGDBG_DECLARE_MEMLEAK_COUNTER();
481     
482   private:
483
484     // The only valid constructor requires a number of fields
485     CdlPackageBody(std::string /* name */, CdlConfiguration, std::string /* directory */);
486
487     // Other constructors are illegal
488     CdlPackageBody();
489     CdlPackageBody(const CdlPackageBody&);
490     CdlPackageBody& operator=(const CdlPackageBody&);
491
492     bool loaded_for_template;
493     bool loaded_for_hardware;
494     
495     enum {
496         CdlPackageBody_Invalid  = 0,
497         CdlPackageBody_Magic    = 0x1d7c0d43
498     } cdlpackagebody_cookie;
499 };
500
501 //}}}
502 //{{{  CdlComponent class                       
503
504 // ----------------------------------------------------------------------------
505 // Similarly components just inherit from the appropriate base classes.
506
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
514 {
515     friend class CdlTest;
516
517   public:
518
519     ~CdlComponentBody();
520     static int          parse_component(CdlInterpreter, int, const char*[]);
521     static int          parse_script(CdlInterpreter, int, const char*[]);
522
523     // Propagation support. Because of multiple virtual inheritance
524     // it is necessary to invoke the container and valuable
525     // update members.
526     virtual void update(CdlTransaction, CdlUpdate);
527     
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*[]);
532     
533     virtual std::string get_class_name() const;
534     bool                check_this(cyg_assert_class_zeal = cyg_quick) const;
535     CYGDBG_DECLARE_MEMLEAK_COUNTER();
536     
537   private:
538
539     // The only valid constructor requires a name.
540     CdlComponentBody(std::string);
541     
542     enum {
543         CdlComponentBody_Invalid  = 0,
544         CdlComponentBody_Magic    = 0x6359d9a7
545     } cdlcomponentbody_cookie;
546     
547     // Other constructors are illegal
548     CdlComponentBody();
549     CdlComponentBody(const CdlComponentBody&);
550     CdlComponentBody& operator=(const CdlComponentBody&);
551 };
552
553 //}}}
554 //{{{  CdlOption class                          
555
556 // ----------------------------------------------------------------------------
557 // Again options just inherit their functionality from the base classes.
558
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
565 {
566     friend class CdlTest;
567     
568   public:
569     ~CdlOptionBody();
570     
571     static int          parse_option(CdlInterpreter, int, const char*[]);
572     
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*[]);
577     
578     virtual std::string get_class_name() const;
579     bool                check_this(cyg_assert_class_zeal = cyg_quick) const;
580     CYGDBG_DECLARE_MEMLEAK_COUNTER();
581
582   private:
583     CdlOptionBody(std::string);
584
585     enum {
586         CdlOptionBody_Invalid   = 0,
587         CdlOptionBody_Magic     = 0x1c1162d1
588     } cdloptionbody_cookie;
589     
590     CdlOptionBody();
591     CdlOptionBody(const CdlOptionBody&);
592     CdlOptionBody& operator=(const CdlOptionBody&);
593 };
594
595 //}}}
596
597 #endif  /* !__CDL_HXX */
598 // EOF cdl.hxx