]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/common/cdl_exec.cxx
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / common / cdl_exec.cxx
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5 // Copyright (C) 2003 John Dallaway
6 //
7 // This program is part of the eCos host tools.
8 //
9 // This program is free software; you can redistribute it and/or modify it 
10 // under the terms of the GNU General Public License as published by the Free 
11 // Software Foundation; either version 2 of the License, or (at your option) 
12 // any later version.
13 // 
14 // This program is distributed in the hope that it will be useful, but WITHOUT 
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
16 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
17 // more details.
18 // 
19 // You should have received a copy of the GNU General Public License along with
20 // this program; if not, write to the Free Software Foundation, Inc., 
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 //
23 // ----------------------------------------------------------------------------
24 //                                                                          
25 //####COPYRIGHTEND####
26 //==========================================================================
27 //
28 //      cdl_exec.cxx
29 //
30 //      The implementation of each ecosconfig command
31 //
32 //==========================================================================
33 //==========================================================================
34 //#####DESCRIPTIONBEGIN####                                             
35 //
36 // Author(s):           jld
37 // Date:                1999-11-08
38 //
39 //####DESCRIPTIONEND####
40 //==========================================================================
41
42 #ifdef _MSC_VER
43 #include <direct.h> /* for getcwd() */
44 #else
45 #include <unistd.h> /* for getcwd() */
46 #endif
47 #ifdef __CYGWIN__
48 #include <windows.h>
49 #include <sys/param.h>  /* for MAXPATHLEN */
50 #include <sys/cygwin.h> /* for cygwin_conv_to_win32_path() */
51 #endif
52 #include "build.hxx"
53 #include "cdl_exec.hxx"
54
55 // ----------------------------------------------------------------------------
56 bool cdl_exec::quiet            = false;
57 bool cdl_exec::verbose          = false;
58 bool cdl_exec::ignore_errors    = false;
59 bool cdl_exec::no_updates       = false;
60 bool cdl_exec::debug_level_set  = false;
61 int  cdl_exec::debug_level      = 0;
62
63 cdl_exec::cdl_exec (const std::string repository_arg, const std::string savefile_arg,
64                     const std::string install_arg, bool no_resolve_arg)
65     : repository(repository_arg),
66       savefile(savefile_arg),
67       install_prefix(install_arg),
68       no_resolve(no_resolve_arg),
69       pkgdata (NULL),
70       interp (NULL),
71       config (NULL)
72 {
73
74     // The inference callback does not actually do anything at present.
75     // In future it may be useful for diagnostic purposes.
76     CdlTransactionBody::set_inference_callback_fn (&inference_callback);
77     
78     // Automatic inference is always disabled. The inference engine
79     // only gets invoked explicitly, after a suitable transaction callback
80     // has been invoked. The problem here is that the transaction callback
81     // has to report changes made by the inference engine but there is
82     // no way of distinguishing between inferred values that come out of
83     // savefiles and inferred values determined by the inference engine.
84     CdlTransactionBody::disable_automatic_inference ();
85 }
86
87 void
88 cdl_exec::set_quiet_mode(bool new_val)
89 {
90     quiet = new_val;
91 }
92
93 void
94 cdl_exec::set_verbose_mode(bool new_val)
95 {
96     verbose = new_val;
97     CdlPackagesDatabaseBody::set_verbose(new_val);
98 }
99
100 void
101 cdl_exec::set_ignore_errors_mode(bool new_val)
102 {
103     ignore_errors = new_val;
104 }
105
106 void
107 cdl_exec::set_no_updates_mode(bool new_val)
108 {
109     no_updates = new_val;
110 }
111
112 void
113 cdl_exec::set_debug_level(int new_level)
114 {
115     debug_level_set = true;
116     debug_level = new_level;
117 }
118
119 // ----------------------------------------------------------------------------
120 void
121 cdl_exec::init(bool load_config)
122 {
123     pkgdata = CdlPackagesDatabaseBody::make(repository, &diagnostic_handler, &diagnostic_handler);
124     interp  = CdlInterpreterBody::make();
125     if (load_config) {
126         config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler);
127     }
128 }
129
130 // ----------------------------------------------------------------------------
131 void
132 cdl_exec::delete_cdl_data ()
133 {
134     if (0 != config) {
135         delete config;
136         config = 0;
137     }
138     if (0 != interp) {
139         delete interp;
140         interp = 0;
141     }
142     if (0 != pkgdata) {
143         delete pkgdata;
144         pkgdata = 0;
145     }
146 }
147
148 // ----------------------------------------------------------------------------
149 bool cdl_exec::cmd_new (const std::string cdl_hardware,
150                         const std::string cdl_template /* = "default" */,
151                         const std::string cdl_version /* = "" */)
152 {
153     bool status = false;
154     try {
155         init(false);
156         
157         config = CdlConfigurationBody::make ("eCos", pkgdata, interp);
158
159         // The hardware and template should be loaded in a single transaction.
160         // Validating the target name etc. can be left to libcdl.
161         CdlLocalTransaction transact(config);
162         config->set_hardware(transact.get(), resolve_hardware_alias(cdl_hardware), &diagnostic_handler, &diagnostic_handler);
163         config->set_template(transact.get(), cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler);
164         transact.body();
165         transact.destroy();
166
167         if (debug_level_set) {
168             this->update_debug_level();
169         }
170         
171         // Unless inference has been suppressed, make sure that the
172         // inference engine gets invoked and that its results get
173         // reported.
174         if (!no_resolve) {
175             CdlTransactionBody::set_callback_fn(&transaction_callback);
176             config->resolve_all_conflicts();
177         }
178
179         // Now report any conflicts which the inference engine could not report. 
180         report_conflicts();
181
182         // A savefile should be generated/updated even if there are conflicts.
183         // Otherwise the user does not have a chance to edit the savefile
184         // and fix things.
185         if (!no_updates) {
186             config->save (savefile);
187         }
188         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
189             status = true;
190         }
191     } catch (CdlStringException exception) {
192         exception_handler (exception);
193     } catch (...) {
194         exception_handler ();
195     }
196
197     delete_cdl_data ();
198     return status;
199 }
200
201 // ----------------------------------------------------------------------------
202 bool
203 cdl_exec::cmd_target (const std::string cdl_target)
204 {
205     bool status = false;
206     try {
207         init(true);
208         config->set_hardware (resolve_hardware_alias (cdl_target), &diagnostic_handler, &diagnostic_handler);
209         if (debug_level_set) {
210             this->update_debug_level();
211         }
212         if (!no_resolve) {
213             CdlTransactionBody::set_callback_fn(&transaction_callback);
214             config->resolve_all_conflicts();
215         }
216         report_conflicts();
217         if (!no_updates) {
218             config->save (savefile);
219         }
220         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
221             status = true;
222         }
223     } catch (CdlStringException exception) {
224         exception_handler (exception);
225     } catch (...) {
226         exception_handler ();
227     }
228
229     delete_cdl_data ();
230     return status;
231 }
232
233 // ----------------------------------------------------------------------------
234 bool
235 cdl_exec::cmd_template (const std::string cdl_template, const std::string cdl_version /* = "" */)
236 {
237     bool status = false;
238     try {
239         init(true);
240         config->set_template (cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler);
241         if (debug_level_set) {
242             this->update_debug_level();
243         }
244         if (!no_resolve) {
245             CdlTransactionBody::set_callback_fn(&transaction_callback);
246             config->resolve_all_conflicts();
247         }
248         report_conflicts();
249         if (!no_updates) {
250             config->save (savefile);
251         }
252         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
253             status = true;
254         }
255     } catch (CdlStringException exception) {
256         exception_handler (exception);
257     } catch (...) {
258         exception_handler ();
259     }
260
261     delete_cdl_data ();
262     return status;
263 }
264
265 // ----------------------------------------------------------------------------
266 bool
267 cdl_exec::cmd_export (const std::string cdl_savefile)
268 {
269     bool status = false;
270     try {
271         init(true);
272         if (debug_level_set) {
273             this->update_debug_level();
274         }
275         if (!no_resolve) {
276             CdlTransactionBody::set_callback_fn(&transaction_callback);
277             config->resolve_all_conflicts();
278         }
279         report_conflicts();
280         // Exporting to another file should only happen if the
281         // configuration is conflict-free. This is different from
282         // updating the savefile.
283         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
284             if (!no_updates) {
285                 config->save (cdl_savefile, /* minimal = */ true);
286             }
287             status = true;
288         }
289     } catch (CdlStringException exception) {
290         exception_handler (exception);
291     } catch (...) {
292         exception_handler ();
293     }
294
295     delete_cdl_data ();
296     return status;
297 }
298
299 // ----------------------------------------------------------------------------
300 bool
301 cdl_exec::cmd_import (const std::string cdl_savefile)
302 {
303     bool status = false;
304     try {
305         init(true);
306         config->add(cdl_savefile, &diagnostic_handler, &diagnostic_handler);
307         if (debug_level_set) {
308             this->update_debug_level();
309         }
310         if (!no_resolve) {
311             CdlTransactionBody::set_callback_fn(&transaction_callback);
312             config->resolve_all_conflicts();
313         }
314         report_conflicts();
315         if (!no_updates) {
316             config->save (savefile);
317         }
318         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
319             status = true;
320         }
321     } catch (CdlStringException exception) {
322         exception_handler (exception);
323     } catch (...) {
324         exception_handler ();
325     }
326
327     delete_cdl_data ();
328     return status;
329 }
330
331 // ----------------------------------------------------------------------------
332 bool
333 cdl_exec::cmd_add (const std::vector<std::string> cdl_packages)
334 {
335     bool status = false;
336     try {
337         init(true);
338         for (unsigned int n = 0; n < cdl_packages.size (); n++) {
339             config->load_package (resolve_package_alias (cdl_packages [n]), "", &diagnostic_handler, &diagnostic_handler);
340         }
341         if (debug_level_set) {
342             this->update_debug_level();
343         }
344         if (!no_resolve) {
345             CdlTransactionBody::set_callback_fn(&transaction_callback);
346             config->resolve_all_conflicts();
347         }
348         report_conflicts();
349         if (!no_updates) {
350             config->save (savefile);
351         }
352         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
353             status = true;
354         }
355     } catch (CdlStringException exception) {
356         exception_handler (exception);
357     } catch (...) {
358         exception_handler ();
359     }
360
361     delete_cdl_data ();
362     return status;
363 }
364
365 // ----------------------------------------------------------------------------
366 bool
367 cdl_exec::cmd_remove (const std::vector<std::string> cdl_packages)
368 {
369     unsigned int n;
370     bool status = false;
371     try {
372         init(true);
373         for (n = 0; n < cdl_packages.size (); n++) {
374             if (! config->lookup (resolve_package_alias (cdl_packages [n]))) {
375                 throw CdlStringException ("Unknown package " + cdl_packages [n]);
376             }
377         }
378         for (n = 0; n < cdl_packages.size (); n++) {
379             config->unload_package (resolve_package_alias (cdl_packages [n]));
380         }
381         if (debug_level_set) {
382             this->update_debug_level();
383         }
384         if (!no_resolve) {
385             CdlTransactionBody::set_callback_fn(&transaction_callback);
386             config->resolve_all_conflicts();
387         }
388         report_conflicts();
389         if (!no_updates) {
390             config->save (savefile);
391         }
392         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
393             status = true;
394         }
395     } catch (CdlStringException exception) {
396         exception_handler (exception);
397     } catch (...) {
398         exception_handler ();
399     }
400
401     delete_cdl_data ();
402     return status;
403 }
404
405 // ----------------------------------------------------------------------------
406 bool
407 cdl_exec::cmd_version (const std::string cdl_version, const std::vector<std::string> cdl_packages)
408 {
409     bool status = false;
410     try {
411         init(true);
412         for (unsigned int n = 0; n < cdl_packages.size (); n++) {
413             config->change_package_version(resolve_package_alias (cdl_packages [n]), cdl_version,
414                                            &diagnostic_handler, &diagnostic_handler, true);
415         }
416         if (debug_level_set) {
417             this->update_debug_level();
418         }
419         if (!no_resolve) {
420             CdlTransactionBody::set_callback_fn(&transaction_callback);
421             config->resolve_all_conflicts();
422         }
423         report_conflicts();
424         if (!no_updates) {
425             config->save (savefile);
426         }
427         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
428             status = true;
429         }
430     } catch (CdlStringException exception) {
431         exception_handler (exception);
432     } catch (...) {
433         exception_handler ();
434     }
435
436     delete_cdl_data ();
437     return status;
438 }
439
440 // ----------------------------------------------------------------------------
441 bool
442 cdl_exec::cmd_tree ()
443 {
444     bool status = false;
445     try {
446         init(true);
447         if (debug_level_set) {
448             this->update_debug_level();
449         }
450         if (!no_resolve) {
451             CdlTransactionBody::set_callback_fn(&transaction_callback);
452             config->resolve_all_conflicts();
453         }
454         report_conflicts();
455         if (!no_updates) {
456             config->save (savefile);
457         }
458         // A build tree should only be generated if there are no conflicts,
459         // and suppressed if -n is given.
460         if (no_updates) {
461             // Do nothing
462         }
463         else if (ignore_errors || (0 == config->get_all_conflicts().size())) {
464 #ifdef _MSC_VER
465             char cwd [_MAX_PATH + 1];
466 #else
467             char cwd [PATH_MAX + 1];
468 #endif
469             getcwd (cwd, sizeof cwd);
470 #ifdef __CYGWIN__
471             char cwd_win32 [MAXPATHLEN + 1];
472             cygwin_conv_to_win32_path (cwd, cwd_win32);
473             generate_build_tree (config, cwd_win32, install_prefix);
474 #else
475             generate_build_tree (config, cwd, install_prefix);
476 #endif
477             config->generate_config_headers (install_prefix.empty () ? "install/include/pkgconf" : install_prefix + "/include/pkgconf");
478             status = true;
479 #ifdef __CYGWIN__
480             char buf[100];
481             strcpy(buf, "mount.exe -f -t -u x: /ecos-x");
482             //printf("Cwd_win32: %s\n", cwd_win32);
483
484             if ( cwd_win32[1] == ':' )
485             {
486                 buf[19] = tolower(cwd_win32[0]);
487                 buf[28] = tolower(cwd_win32[0]);
488                 system(buf);
489             }
490
491             //printf("Repository: %s\n", repository.c_str());
492
493             if ( repository[1] == ':' )
494             {
495                 buf[19] = tolower(repository[0]);
496                 buf[28] = tolower(repository[0]);
497                 system(buf);
498             }
499             if ( !install_prefix.empty() )
500             {
501                 //printf("Install prefix: %s\n", install_prefix.c_str());
502                 if ( install_prefix[1] == ':' )
503                 {
504                     buf[19] = tolower(install_prefix[0]);
505                     buf[28] = tolower(install_prefix[0]);
506                     system(buf);
507                 }
508             }
509 #endif
510         } else {
511             printf("\nUnable to generate build tree, this configuration still contains conflicts.\n");
512             printf("Either resolve the conflicts or use --ignore-errors\n");
513         }
514     } catch (CdlStringException exception) {
515         exception_handler (exception);
516     } catch (...) {
517         exception_handler ();
518     }
519
520     delete_cdl_data ();
521     return status;
522 }
523
524 // ----------------------------------------------------------------------------
525 bool
526 cdl_exec::cmd_list ()
527 {
528     bool status = false;
529     try {
530         init(false);
531
532         // list the installed packages
533         std::vector<std::string> packages = pkgdata->get_packages ();
534         std::sort (packages.begin (), packages.end ());
535         for (unsigned int package = 0; package < packages.size (); package++) {
536             const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [package]);
537             printf ("Package %s (%s):\n aliases:", packages [package].c_str (), aliases [0].c_str ());
538             for (unsigned int alias = 1; alias < aliases.size (); alias++) {
539                 printf (" %s", aliases [alias].c_str ());
540             }
541             const std::vector<std::string> & versions = pkgdata->get_package_versions (packages [package]);
542             printf ("\n versions:");
543             for (unsigned int version = 0; version < versions.size (); version++) {
544                 printf (" %s", versions [version].c_str ());
545             }
546             printf ("\n");
547         }
548
549         // list the available targets
550         std::vector<std::string> targets = pkgdata->get_targets ();
551         std::sort (targets.begin (), targets.end ());
552         for (unsigned int target = 0; target < targets.size (); target++) {
553             const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [target]);
554             printf ("Target %s (%s):\n aliases:", targets [target].c_str (), aliases [0].c_str ());
555             for (unsigned int alias = 1; alias < aliases.size (); alias++) {
556                 printf (" %s", aliases [alias].c_str ());
557             }
558             printf ("\n");
559         }
560
561         // list the available templates
562         std::vector<std::string> templates = pkgdata->get_templates ();
563         std::sort (templates.begin (), templates.end ());
564         for (unsigned int templ = 0; templ < templates.size (); templ++) {
565             const std::vector<std::string> & versions = pkgdata->get_template_versions (templates [templ]);
566             printf ("Template %s:\n versions:", templates [templ].c_str ());
567             for (unsigned int version = 0; version < versions.size (); version++) {
568                 printf (" %s", versions [version].c_str ());
569             }
570             printf ("\n");
571         }
572
573         status = true;
574     } catch (CdlStringException exception) {
575         exception_handler (exception);
576     } catch (...) {
577         exception_handler ();
578     }
579
580     delete_cdl_data ();
581     return status;
582 }
583
584 // ----------------------------------------------------------------------------
585 bool
586 cdl_exec::cmd_check ()
587 {
588     bool status = false;
589     unsigned int n;
590
591     try {
592         init(true);
593         // check() should never invoke the inference engine. The user
594         // wants to determine the current status, which should not
595         // change.
596         // However, updating the savefile is worthwhile because it
597         // will now contain more accurate information about the state.
598         // Enabling/disabling debugs is allowed for now because that
599         // is unlikely to introduce conflicts.
600         if (debug_level_set) {
601             this->update_debug_level();
602         }
603         if (!no_updates) {
604             config->save (savefile);
605         }
606
607         // report current target and template
608         printf ("Target: %s\n", config->get_hardware ().c_str ());
609         printf ("Template: %s\n", config->get_template ().c_str ());
610         std::vector<std::string> template_packages = pkgdata->get_template_packages (config->get_template ());
611         const std::vector<std::string> & hardware_packages = pkgdata->get_target_packages (config->get_hardware ());
612         for (n = 0; n < hardware_packages.size (); n++) {
613             template_packages.push_back (hardware_packages [n]);
614         }
615
616         // report loaded packages not in the templates
617         const std::vector<CdlLoadable> & loadables = config->get_loadables ();
618         std::vector<std::string> added_packages;
619         std::vector<CdlLoadable>::const_iterator loadable_i;
620         for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) {
621             const CdlNode & node = dynamic_cast<CdlNode> (* loadable_i);
622             if (template_packages.end () == std::find (template_packages.begin (), template_packages.end (), node->get_name ())) {
623                 added_packages.push_back (node->get_name ());
624             }
625         }
626         if (added_packages.size ()) {
627             printf ("Added:\n");
628         }
629         for (n = 0; n < added_packages.size (); n++) {
630             printf (" %s\n", added_packages [n].c_str ());
631         }
632
633         // report template packages not in the configuration
634         std::vector<std::string> removed_packages;
635         for (n = 0; n < template_packages.size (); n++) {
636             if (! config->lookup (template_packages [n])) {
637                 removed_packages.push_back (template_packages [n]);
638             }
639         }
640         if (removed_packages.size ()) {
641             printf ("Removed:\n");
642         }
643         for (n = 0; n < removed_packages.size (); n++) {
644             printf (" %s\n", removed_packages [n].c_str ());
645         }
646
647         // report packages of non-default version
648         std::vector<CdlValuable> version_packages;
649         for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) {
650             const CdlValuable & valuable = dynamic_cast<CdlValuable> (* loadable_i);
651             if (pkgdata->get_package_versions (valuable->get_name ()) [0] != valuable->get_value ()) {
652                 version_packages.push_back (valuable);
653             }
654         }
655         if (version_packages.size ()) {
656             printf ("Version(s):\n");
657         }
658         for (n = 0; n < version_packages.size (); n++) {
659             printf (" %s %s\n", version_packages [n]->get_name ().c_str (), version_packages [n]->get_value ().c_str ());
660         }
661
662         // report conflicts
663         const std::list<CdlConflict> & conflicts = config->get_all_conflicts ();
664         if (conflicts.size ()) {
665             printf ("%u conflict(s):\n", conflicts.size ());
666         } else {
667             printf ("No conflicts\n");
668         }
669         report_conflicts();
670
671         status = true;
672     } catch (CdlStringException exception) {
673         exception_handler (exception);
674     } catch (...) {
675         exception_handler ();
676     }
677
678     delete_cdl_data ();
679     return status;
680 }
681
682 // ----------------------------------------------------------------------------
683 bool
684 cdl_exec::cmd_resolve ()
685 {
686     bool status = false;
687
688     try {
689         init(true);
690         if (debug_level_set) {
691             this->update_debug_level();
692         }
693         CdlTransactionBody::set_callback_fn(&transaction_callback);
694         config->resolve_all_conflicts ();
695         report_conflicts();
696         if (!no_updates) {
697             config->save (savefile);
698         }
699         if (ignore_errors || (0 == config->get_all_conflicts().size())) {
700             status = true;
701         }
702     } catch (CdlStringException exception) {
703         exception_handler (exception);
704     } catch (...) {
705         exception_handler ();
706     }
707
708     delete_cdl_data ();
709     return status;
710 }
711
712 // ----------------------------------------------------------------------------
713 // The inference callback. This could give some useful diagnostics, or it
714 // could do useful things when running in some interactive mode. In batch
715 // mode it should not do anything.
716
717 CdlInferenceCallbackResult
718 cdl_exec::inference_callback (CdlTransaction transaction)
719 {
720     return CdlInferenceCallbackResult_Continue;
721 }
722
723 // ----------------------------------------------------------------------------
724 // Output a message with indentation after newlines.
725 static void
726 dump_string(unsigned int indent, const std::string& str)
727 {
728     bool newline_pending = false;
729     unsigned int i, j;
730     for (i = 0; i < str.size(); i++) {
731         if (newline_pending) {
732             putchar('\n');
733             if ('\n' != str[i]) {
734                 for (j = 0; j < indent; j++) {
735                     putchar(' ');
736                 }
737             }
738             newline_pending = false;
739         }
740         if ('\n' == str[i]) {
741             newline_pending = true;
742         } else {
743             putchar(str[i]);
744         }
745     }
746     if (newline_pending) {
747         putchar('\n');  // But not the indentation.
748     }
749 }
750
751 // ----------------------------------------------------------------------------
752 // The transaction callback. This should report any changes that have been
753 // made to the configuration. The amount of output depends on the verbosity
754 // level selected by the user.
755 //
756 // 1) quiet     - no output at all
757 // 2) default   - list updates done by the inference engine.
758 // 3) verbose   - this does not currently add anything.
759 // 
760 // There is no reporting of new or resolved conflicts. Resolved
761 // conflicts are probably of no interest in batch mode. New conflicts
762 // will be handled by report_conflicts(). There is also no information
763 // given about active state changes, although arguably there should be
764 // especially in the case of containers.
765
766 void
767 cdl_exec::transaction_callback(const CdlTransactionCallback& callback_data)
768 {
769     if (quiet) {
770         return;
771     }
772
773     unsigned int i;
774     for (i = 0; i < callback_data.value_changes.size(); i++) {
775         CdlValuable valuable = callback_data.value_changes[i];
776         if (CdlValueSource_Inferred == valuable->get_source()) {
777             CdlEvalContext context(0, valuable, 0);
778             CdlSimpleValue simple_val;
779             CdlSimpleValue::eval_valuable(context, valuable, simple_val);
780             std::string msg = std::string("U ") + valuable->get_name() + ", new inferred value ";
781             std::string value = simple_val.get_value();
782             if ("" == value) {
783                 msg += "\"\"";
784             } else {
785                 msg += value;
786             }
787             msg += "\n";
788             dump_string(4, msg);
789         }
790     }
791 }
792
793 // ----------------------------------------------------------------------------
794 // Report the remaining conflicts in the configuration. These indicate
795 // problems that the user should fix before going further with the
796 // configuration, e.g. before generating a build tree.
797 //
798 // Quiet verbosity level has no effect on this, but at the verbose level
799 // it is a good idea to look for a possible solution to the conflict.
800
801
802 void
803 cdl_exec::report_conflicts()
804 {
805     const std::list<CdlConflict>& all_conflicts = config->get_all_conflicts();
806     std::list<CdlConflict>::const_iterator conf_i;
807     for (conf_i = all_conflicts.begin(); conf_i != all_conflicts.end(); conf_i++) {
808         CdlNode     node = (*conf_i)->get_node();
809
810         std::string msg = std::string("C ") + node->get_name() + ", " + (*conf_i)->get_explanation() + "\n";
811         dump_string(2, msg);
812
813         if (verbose && (*conf_i)->resolution_implemented()) {
814             // See if there is a possible solution to this conflict.
815             // This involves creating a transaction, invoking the
816             // inference engine, and cancelling the transaction
817             // (thus making sure that nothing actually changes).
818             //
819             // NOTE: at some stage libcdl may keep track of solutions
820             // globally. However, although it will know when a solution
821             // becomes invalid it will not necessarily try to resolve
822             // all global conflicts after every change, so attempting
823             // to do this in a transaction may still be necessary.
824             CdlTransaction transact = CdlTransactionBody::make(config);
825             transact->resolve(*conf_i);
826             if ((*conf_i)->has_known_solution()) {
827                 std::string soln_msg = "  Possible solution:\n";
828                 const std::vector<std::pair<CdlValuable, CdlValue> > & soln = (*conf_i)->get_solution();
829                 unsigned int i;
830                 for (i = 0; i < soln.size(); i++) {
831                     CdlValuable valuable = soln[i].first;
832                     soln_msg += valuable->get_name();
833                     soln_msg += " -> ";
834                     switch(valuable->get_flavor()) {
835                       case CdlValueFlavor_Bool :
836                         if (!soln[i].second.is_enabled()) {
837                             soln_msg += "0 (disabled)";
838                         } else {
839                             soln_msg += "1 (enabled)";
840                         }
841                         break;
842                       case CdlValueFlavor_Data:
843                         soln_msg += soln[i].second.get_value();
844                         break;
845                       case CdlValueFlavor_BoolData:
846                         if (!soln[i].second.is_enabled()) {
847                             soln_msg += "0 " + soln[i].second.get_value();
848                         } else {
849                             soln_msg += "1 " + soln[i].second.get_value();
850                         }
851                         break;
852                         // An option with flavor none cannot be involved
853                         // in a solution.
854                       default:
855                         soln_msg += "<internal error>";
856                         break;
857                     }
858                     soln_msg += "\n";
859                 }
860                 
861 #if 0
862                 // FIXME: currently this member only works for nested sub-transactions.
863                 if (transact->user_confirmation_required()) {
864                     msg += "This change affects previous user settings.\n";
865                 }
866 #endif                
867                 dump_string(4, soln_msg);
868             }
869             transact->cancel();
870             delete transact;
871         }
872     }
873 }
874
875 // ----------------------------------------------------------------------------
876 void
877 cdl_exec::diagnostic_handler (std::string message)
878 {
879     printf ("%s\n", message.c_str ());
880 }
881
882 void cdl_exec::exception_handler (CdlStringException exception) {
883     printf ("%s\n", exception.get_message ().c_str ());
884 }
885
886 void
887 cdl_exec::exception_handler ()
888 {
889     printf ("Unknown error\n");
890 }
891
892
893 // ----------------------------------------------------------------------------
894 std::string
895 cdl_exec::resolve_package_alias (const std::string alias)
896 {
897     std::string package = alias;
898
899     if (! pkgdata->is_known_package (alias)) { // if the alias is not a package name
900         const std::vector<std::string> & packages = pkgdata->get_packages (); // get packages
901         for (unsigned int n = 0; n < packages.size (); n++) { // for each package
902             const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [n]); // get package aliases
903             if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found
904                 package = packages [n]; // note the package
905                 break;
906             }
907         }
908     }
909     return package;
910 }
911
912 std::string
913 cdl_exec::resolve_hardware_alias (const std::string alias)
914 {
915     std::string target = alias;
916
917     if (! pkgdata->is_known_target (alias)) { // if the alias is not a target name
918         const std::vector<std::string> & targets = pkgdata->get_targets (); // get targets
919         for (unsigned int n = 0; n < targets.size (); n++) { // for each target
920             const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [n]); // get target aliases
921             if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found
922                 target = targets [n]; // note the target
923                 break;
924             }
925         }
926     }
927     return target;
928 }
929
930 // ----------------------------------------------------------------------------
931 // Enable or disable debugging in a configuration.
932 void
933 cdl_exec::update_debug_level()
934 {
935     CdlNode node = config->lookup("CYGPKG_INFRA_DEBUG");
936     CdlValuable valuable = 0;
937     if (0 != node) {
938         valuable = dynamic_cast<CdlValuable>(node);
939     }
940     if (0 == valuable) {
941         throw CdlStringException("Cannot enable or disable debugging, the infrastructure package is absent");
942     }
943     
944     if (debug_level > 0) {
945         valuable->enable(CdlValueSource_User);
946     } else {
947         valuable->disable(CdlValueSource_User);
948     }
949 }