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