1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
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)
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
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.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
27 #include "ConfigToolDoc.h"
32 #include "ProjectManager.h"
38 #include "CdlPackagesDialog.h"
39 #include "ConfigItem.h"
40 #include "ConfigTool.h"
41 #include "ControlView.h"
42 #include "FailingRulesDialog.h"
43 #include "FolderDialog.h"
44 #include "IdleMessage.h"
47 #include "RegionGeneralPage.h"
49 #include "RulesView.h"
50 #include "SectionGeneralPage.h"
51 #include "SectionRelocationPage.h"
56 #define INCLUDEFILE <string>
57 #include "IncludeSTL.h"
58 #define INCLUDEFILE "build.hxx"
59 #include "IncludeSTL.h"
64 static char THIS_FILE[] = __FILE__;
67 const CFileName &CConfigToolDoc::DefaultExternalBrowser()
69 static bool bFirstTime=true;
71 const CFileName strFile(CFileName::GetTempPath()+_T("index.html"));
73 if(f.Open(strFile,CFile::modeCreate|CFile::modeWrite)){
75 bool rc=((int)FindExecutable(strFile,_T("."),m_strDefaultExternalBrowser.GetBuffer(MAX_PATH))>32);
76 m_strDefaultExternalBrowser.ReleaseBuffer();
78 m_strDefaultExternalBrowser=_T("");
80 ::DeleteFile(strFile);
84 return m_strDefaultExternalBrowser;
87 CFileName CConfigToolDoc::m_strDefaultExternalBrowser;
89 void CConfigToolDoc::CheckRadios()
91 for(int nItem=0;nItem<ItemCount();nItem++){
92 CConfigItem *pItem=Item(nItem);
93 if(pItem->HasRadio () && pItem==pItem->FirstRadio()){
95 CConfigItem *pFirstSet=NULL;
96 for(CConfigItem *pSibItem=pItem;pSibItem;pSibItem=pSibItem->NextRadio()){
97 if(pSibItem->IsEnabled ()){
100 strMsg+=pSibItem->Macro ();
106 if(!strMsg.IsEmpty()){
107 CConfigTool::Log(_T("%s, multiple radio buttons are set: %s%s"),
108 pItem->Macro(),pFirstSet->Macro(),strMsg);
109 } else if(!pFirstSet){
110 CConfigTool::Log(_T("%s, no radio buttons are set"),pItem->Macro());
116 // Find the ConfigItem referencing the given CdlValuable
117 CConfigItem * CConfigToolDoc::Find (CdlValuable v)
119 for(int nItem=0;nItem<ItemCount();nItem++){
120 CConfigItem *pItem=Item(nItem);
121 if(v==pItem->GetCdlValuable()){
128 CConfigItem * CConfigToolDoc::Find(const CString & strWhat,WhereType where)
130 for(int nItem=0;nItem<ItemCount();nItem++){
131 CConfigItem *pItem=Item(nItem);
132 if(0==pItem->StringValue(where).Compare(strWhat)){
139 void CConfigToolDoc::OnMLTNewRegion()
141 // create the property sheet
143 CPropertySheet prsRegionSheet (IDS_NEW_REGION_SHEET_TITLE, CConfigTool::GetMLTView());
145 // add the property pages
147 CRegionGeneralPage prpGeneral;
150 prsRegionSheet.AddPage (&prpGeneral);
151 prsRegionSheet.AddPage (&prpNote);
153 // setup initial values
155 prpGeneral.m_strRegionName = _T("");
156 prpGeneral.m_dwRegionStartAddress = 0;
157 prpGeneral.m_dwRegionSize = 0;
159 // show property sheet
161 if (prsRegionSheet.DoModal () == IDOK)
163 if (int nErrorCode = MemoryMap.create_memory_region (CUtils::UnicodeToStdStr(prpGeneral.m_strRegionName), prpGeneral.m_dwRegionStartAddress, prpGeneral.m_dwRegionSize, (prpGeneral.m_bRegionReadOnly ? read_only : read_write), CUtils::UnicodeToStdStr(prpNote.m_strNote)))
164 ErrorBox (IDS_ERR_MEMMAP_REGION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode);
168 UpdateAllViews (NULL, MemLayoutChanged);
173 void CConfigToolDoc::ErrorBox (UINT uIDSIntro, UINT uIDSError)
175 CString strIntro, strError;
176 strIntro.LoadString (uIDSIntro);
177 strError.LoadString (uIDSError);
178 AfxMessageBox (strIntro + _T("\n\n") + strError);
181 void CConfigToolDoc::OnMLTNewSection()
183 // create the property sheet
185 CPropertySheet prsSectionSheet (IDS_NEW_SECTION_SHEET_TITLE, CConfigTool::GetMLTView());
187 // add the property pages
189 CSectionGeneralPage prpGeneral;
190 CSectionRelocationPage prpRelocation;
193 prsSectionSheet.AddPage (&prpGeneral);
194 prsSectionSheet.AddPage (&prpRelocation);
195 prsSectionSheet.AddPage (&prpNote);
197 // initialise for a new section
199 prpGeneral.m_bNameLinkerDefined = TRUE;
200 prpGeneral.m_strNameLinker = _T("");
201 prpRelocation.m_bRelocates = FALSE;
202 prpRelocation.m_bNewSection = TRUE;
204 // show property sheet
206 if (prsSectionSheet.DoModal () == IDOK)
208 mem_anchor initial_anchor, final_anchor;
209 mem_address initial_address;
210 CString strInitialRelativeName = _T("");
212 if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location
213 final_anchor = absolute;
214 else // final location is a relative location
215 final_anchor = relative;
217 if (prpRelocation.m_bRelocates) // if the section relocates
219 if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location
221 initial_anchor = absolute;
223 else // initial location is a relative location
225 strInitialRelativeName = prpRelocation.m_strInitialRelativeName;
226 initial_anchor = relative;
228 initial_address = prpRelocation.m_dwInitialAddress;
232 strInitialRelativeName = prpGeneral.m_strFinalRelativeName;
233 initial_anchor = final_anchor;
234 initial_address = prpGeneral.m_dwFinalAddress;
238 if (int nErrorCode = MemoryMap.create_memory_section (CUtils::UnicodeToStdStr(prpGeneral.m_bNameLinkerDefined ? prpGeneral.m_strNameLinker : prpGeneral.m_strNameUser), prpGeneral.m_dwSectionSize, prpGeneral.m_dwAlignment, initial_anchor, CUtils::UnicodeToStdStr(strInitialRelativeName), initial_address, final_anchor, CUtils::UnicodeToStdStr(prpGeneral.m_strFinalRelativeName), prpGeneral.m_dwFinalAddress, prpRelocation.m_bRelocates, false, prpGeneral.m_bNameLinkerDefined, CUtils::UnicodeToStdStr(prpNote.m_strNote)))
239 ErrorBox (IDS_ERR_MEMMAP_SECTION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode);
243 UpdateAllViews (NULL, MemLayoutChanged);
248 void CConfigToolDoc::OnMLTDelete()
250 if (strSelectedSection != _T("")) // a section is selected
252 if (MemoryMap.delete_memory_section (CUtils::UnicodeToStdStr(strSelectedSection)))
254 strSelectedSection = _T("");
256 UpdateAllViews (NULL, MemLayoutChanged);
259 AfxMessageBox (_T("Could not delete memory section.\n\nMake sure there are no other sections defined relative to this one."));
261 else if (strSelectedRegion != _T("")) // a region is selected
263 if (MemoryMap.delete_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion)))
265 strSelectedRegion = _T("");
267 UpdateAllViews (NULL, MemLayoutChanged);
270 AfxMessageBox (_T("Could not delete memory region.\n\nMake sure it is not in use.")); // FIXME
274 void CConfigToolDoc::ShowRegionProperties()
276 // create the property sheet
279 strTitle.LoadString (IDS_REGION_PROPERTIES_SHEET_TITLE);
280 CPropertySheet prsRegionSheet (strSelectedRegion + _T(" - ") + strTitle, CConfigTool::GetMLTView());
282 // add the property pages
284 CRegionGeneralPage prpGeneral;
287 prsRegionSheet.AddPage (&prpGeneral);
288 prsRegionSheet.AddPage (&prpNote);
290 // set up property sheet values
294 MemoryMap.get_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion), &prpGeneral.m_dwRegionStartAddress, &prpGeneral.m_dwRegionSize, &type, ¬e);
295 prpGeneral.m_strRegionName = strSelectedRegion;
296 prpGeneral.m_bRegionReadOnly = (type == read_only);
297 prpNote.m_strNote = note.c_str ();
299 // show property sheet
301 if (prsRegionSheet.DoModal () == IDOK)
303 if (int nErrorCode = MemoryMap.edit_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion), CUtils::UnicodeToStdStr(prpGeneral.m_strRegionName), prpGeneral.m_dwRegionStartAddress, prpGeneral.m_dwRegionSize, (prpGeneral.m_bRegionReadOnly ? read_only : read_write), CUtils::UnicodeToStdStr(prpNote.m_strNote)))
304 ErrorBox (IDS_ERR_MEMMAP_REGION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode);
308 UpdateAllViews (NULL, MemLayoutChanged);
313 void CConfigToolDoc::ShowSectionProperties()
315 // create the property sheet
318 strTitle.LoadString (IDS_SECTION_PROPERTIES_SHEET_TITLE);
319 CPropertySheet prsSectionSheet (strSelectedSection + _T(" - ") + strTitle, CConfigTool::GetMLTView());
321 // add the property pages
323 CSectionGeneralPage prpGeneral;
324 CSectionRelocationPage prpRelocation;
327 prsSectionSheet.AddPage (&prpGeneral);
328 prsSectionSheet.AddPage (&prpRelocation);
329 prsSectionSheet.AddPage (&prpNote);
331 // setup initial values
333 std::list <mem_section>::iterator section = MemoryMap.find_memory_section (CUtils::UnicodeToStdStr(strSelectedSection));
334 prpGeneral.m_bNameLinkerDefined = (section->linker_defined);
335 if (prpGeneral.m_bNameLinkerDefined)
336 prpGeneral.m_strNameLinker = section->name.c_str ();
339 prpGeneral.m_strNameUser = section->name.c_str ();
340 prpGeneral.m_dwSectionSize = section->size;
343 prpGeneral.m_bFinalAbsolute = (section->final_location->anchor == absolute);
344 if (prpGeneral.m_bFinalAbsolute)
345 prpGeneral.m_dwFinalAddress = section->final_location->address;
348 prpGeneral.m_strFinalRelativeName = MemoryMap.find_preceding_section (section, false)->name.c_str ();
349 prpGeneral.m_dwAlignment = section->alignment;
352 prpRelocation.m_bRelocates = section->relocates;
353 if (prpRelocation.m_bRelocates)
355 prpRelocation.m_bInitialAbsolute = (section->initial_location->anchor == absolute);
356 if (prpRelocation.m_bInitialAbsolute)
357 prpRelocation.m_dwInitialAddress = section->initial_location->address;
359 prpRelocation.m_strInitialRelativeName = MemoryMap.find_preceding_section (section, true)->name.c_str ();
362 prpNote.m_strNote = section->note.c_str ();
364 // show property sheet
366 if (prsSectionSheet.DoModal () == IDOK)
368 mem_anchor initial_anchor, final_anchor;
369 mem_address initial_address;
370 CString strInitialRelativeName = _T("");
372 if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location
373 final_anchor = absolute;
374 else // final location is a relative location
375 final_anchor = relative;
377 if (prpRelocation.m_bRelocates) // if the section relocates
379 if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location
381 initial_anchor = absolute;
383 else // initial location is a relative location
385 strInitialRelativeName = prpRelocation.m_strInitialRelativeName;
386 initial_anchor = relative;
388 initial_address = prpRelocation.m_dwInitialAddress;
392 strInitialRelativeName = prpGeneral.m_strFinalRelativeName;
393 initial_anchor = final_anchor;
394 initial_address = prpGeneral.m_dwFinalAddress;
398 if (int nErrorCode = MemoryMap.edit_memory_section (CUtils::UnicodeToStdStr(strSelectedSection), CUtils::UnicodeToStdStr(prpGeneral.m_bNameLinkerDefined ? prpGeneral.m_strNameLinker : prpGeneral.m_strNameUser), prpGeneral.m_dwSectionSize, prpGeneral.m_dwAlignment, initial_anchor, CUtils::UnicodeToStdStr(strInitialRelativeName), initial_address, final_anchor, CUtils::UnicodeToStdStr(prpGeneral.m_strFinalRelativeName), prpGeneral.m_dwFinalAddress, prpRelocation.m_bRelocates, false, prpGeneral.m_bNameLinkerDefined, CUtils::UnicodeToStdStr(prpNote.m_strNote)))
399 ErrorBox (IDS_ERR_MEMMAP_SECTION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode);
403 UpdateAllViews (NULL, MemLayoutChanged);
408 void CConfigToolDoc::OnMLTProperties()
410 if (strSelectedRegion != _T(""))
411 ShowRegionProperties ();
412 else if (strSelectedSection != _T(""))
413 ShowSectionProperties ();
416 // Choose a default Hal. Do this using clues the installer may have helpfully left behind (PR 18050)
417 // or else if there is only one possible choice, by choosing that one :-).
419 void CConfigToolDoc::ChooseDefaultHal()
422 // Has the installer told us?
423 LPCTSTR pszRegPath=_T("SOFTWARE\\Red Hat\\eCos\\1.2.8");
425 if(ERROR_SUCCESS==RegOpenKeyEx (HKEY_LOCAL_MACHINE, pszRegPath, 0L, KEY_READ, &hKey)){
426 DWORD dwSizePath=MAX_PATH;
428 PTCHAR psz=str.GetBuffer(dwSizePath);
429 if(ERROR_SUCCESS==RegQueryValueEx(hKey, _T("Default Architecture"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){
431 for(int nItem=0;nItem<ItemCount();nItem++){
432 CConfigItem *pItem=Item(nItem);
433 if(pItem->m_pTarget){
434 CString strTarget(pItem->m_pTarget->Name());
435 strTarget.MakeLower();
436 if(-1!=str.Find(strTarget)){
439 if(ERROR_SUCCESS==::RegQueryValueEx(hKey, _T("Default Build Tools Path"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){
440 pItem->m_pTarget->SetBinDir(psz);
441 for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){
442 pSib->SetValue((ItemIntegerType) (pSib==pItem));
444 // pItem->EnableAncestors();
455 // No - choose the Hal according to toolchain
456 for(int nItem=0;nItem<ItemCount();nItem++){
457 CConfigItem *pItem=Item(nItem);
458 if(pItem->m_pTarget){
459 CString strTarget(pItem->m_pTarget->Name());
460 strTarget.MakeLower();
461 for(int j=0;j<m_arstrToolChainPaths.GetSize();j++){
462 CString strTools(m_arstrToolChainPaths[j]);
463 strTools.MakeLower();
464 if(-1!=strTools.Find(strTarget)){
465 for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){
466 pSib->SetValue((ItemIntegerType) (pSib==pItem));
477 bool CConfigToolDoc::SetValue (CConfigItem &ti, double dValue, CdlTransaction transaction/*=NULL*/)
479 ASSERT (ti.Type () == CConfigItem::Double);
481 // test if the new double value is in range
482 const CdlValuable valuable = ti.GetCdlValuable();
483 CdlListValue list_value;
484 CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
485 valuable->get_legal_values ()->eval (context, list_value);
486 if (! list_value.is_member (dValue))
488 if (dValue==valuable->get_double_value(CdlValueSource_Current) || IDNO == CUtils::MessageBoxFT (MB_YESNO, _T("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
489 CUtils::DoubleToStr (dValue), ti.Macro ()))
493 if (! ti.SetValue (dValue,transaction))
499 bool CConfigToolDoc::SetValue(CConfigItem &ti,const CString &strValue, CdlTransaction transaction/*=NULL*/)
501 // warn the user if a modified memory layout is about to be discarded
502 if (MemoryMap.map_modified () && (ti.Macro () == _T("CYG_HAL_STARTUP")) &&
503 (IDCANCEL == CUtils::MessageBoxFT (MB_OKCANCEL, _T("Changes to the current memory layout will be lost."))))
508 case CConfigItem::None:
510 case CConfigItem::Enum:
511 case CConfigItem::String:
512 rc=ti.SetValue(strValue,transaction);
514 case CConfigItem::Integer:
517 rc=CUtils::StrToItemIntegerType(strValue,n) && SetValue(ti,n,transaction);
520 case CConfigItem::Double:
523 rc = CUtils::StrToDouble (strValue, dValue) && SetValue (ti, dValue,transaction);
533 UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti);
538 // Look in registry to match prefixes CYGPKG_HAL_ and CYGHWR_HAL_:
540 bool CConfigToolDoc::GetRunPlatform(CString &strTarget)
542 CRegKeyEx k1(HKEY_CURRENT_USER,_T("Software\\Red Hat\\eCos\\Platforms"), KEY_READ);
544 for(int i=0;k1.QueryKey(i,strKey);i++){
545 CRegKeyEx k2((HKEY)k1,strKey,KEY_READ);
546 // Subkeys' names are the target image names [one of which we aim to return]
547 // Subkeys's values of interest are:
549 // Sim DWORD [optional]
552 CString strPrefix,strMacro;
553 k2.QueryValue(_T("Sim"),dwSim);
554 k2.QueryValue(_T("Prefix"),strPrefix);
555 k2.QueryValue(_T("Macro"),strMacro);
557 CConfigItem *pItem=Find(_T("CYGPKG_HAL_")+strMacro);
558 if(pItem && pItem->IsEnabled()){
559 // We have found what we are looking for - probably
560 pItem=Find(_T("CYGHWR_HAL_")+strMacro+_T("_STARTUP"));
562 // Two platforms apply - choose this one only if the ram startup attribute fits
563 if( (dwSim==0) == (0==pItem->StringValue().CompareNoCase(_T("ram"))) ) {
567 // Only one platform applies
573 return !strTarget.IsEmpty();
576 bool CConfigToolDoc::SetEnabled(CConfigItem &ti, bool bEnabled, CdlTransaction transaction/*=NULL*/)
578 const bool bStatus = ti.SetEnabled (bEnabled,transaction);
582 UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *) &ti);
587 void CConfigToolDoc::AddContents (const CdlContainer container, CConfigItem *pParent)
590 // determine the container contents
592 const std::vector<CdlNode>& contents = container->get_contents ();
593 std::vector<CdlNode>::const_iterator node_i;
594 for (node_i = contents.begin (); node_i != contents.end (); node_i++)
596 const CdlNode node = * node_i;
597 const CdlPackage pkg = dynamic_cast<CdlPackage> (node);
598 const CdlComponent comp = dynamic_cast<CdlComponent> (node);
599 const CdlOption opt = dynamic_cast<CdlOption> (node);
600 const CdlContainer contnr = dynamic_cast<CdlContainer> (node);
602 // if the node in the container is a package, component or option
603 // then it is visible and should be added to the tree
604 if (0 != pkg) // the node is a package
606 CConfigItem * pItem = AddItem (pkg, pParent); // add the package
607 AddContents (pkg, pItem); // add the package contents
609 else if (0 != comp) // the node is a component
611 CConfigItem * pItem = AddItem (comp, pParent); // add the component
612 AddContents (comp, pItem); // add the component contents
614 else if (0 != opt) // the node is an option
615 AddItem (opt, pParent); // add the option
617 else if (0 != contnr) // if the node is a container
618 AddContents (contnr, pParent); // add the container contents
620 // ignore nodes of any other class
624 // Three hack functions.
626 const CString CConfigToolDoc::CurrentPlatform()
629 for(int nItem=0;nItem<ItemCount();nItem++){
630 CConfigItem *pItem=Item(nItem);
631 if(pItem->IsEnabled() && !pItem->Platform().IsEmpty()){
632 return pItem->Platform();
639 // a trivial CDL parse error handler
640 void CConfigToolDoc::CdlParseErrorHandler (std::string message)
642 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
643 pDoc->m_strCdlErrorMessage = message.c_str ();
644 TRACE (_T("CdlParseError: %s\n"), pDoc->m_strCdlErrorMessage);
645 CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
648 // a trivial CDL parse warning handler
649 void CConfigToolDoc::CdlParseWarningHandler (std::string message)
651 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
652 pDoc->m_strCdlErrorMessage = message.c_str ();
653 TRACE (_T("CdlParseWarning: %s\n"), pDoc->m_strCdlErrorMessage);
654 CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
657 // a trivial CDL load error handler
658 void CConfigToolDoc::CdlLoadErrorHandler (std::string message)
660 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
661 pDoc->m_strCdlErrorMessage = message.c_str ();
662 TRACE (_T("CdlLoadError: %s\n"), pDoc->m_strCdlErrorMessage);
663 CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
666 // a trivial CDL load warning handler
667 void CConfigToolDoc::CdlLoadWarningHandler (std::string message)
669 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
670 pDoc->m_strCdlErrorMessage = message.c_str ();
671 TRACE (_T("CdlLoadWarning: %s\n"), pDoc->m_strCdlErrorMessage);
672 CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
675 CdlInferenceCallbackResult CConfigToolDoc::CdlGlobalInferenceHandler(CdlTransaction transaction)
677 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
678 pDoc->m_ConflictsOutcome=NotDone; // prepare for the case that there are no solutions
679 CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
681 std::list<CdlConflict>conflicts1(transaction->get_global_conflicts_with_solutions());
682 const std::vector<CdlConflict>&conflicts2=transaction->get_resolved_conflicts();
683 for (unsigned int i = 0; i < conflicts2.size (); i++) {
684 conflicts1.push_back(conflicts2 [i]);
686 if(conflicts1.size()>0){
687 CFailingRulesDialog dlg(conflicts1,transaction,&pDoc->m_arConflictsOfInterest);
688 rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
689 pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
692 const std::list<CdlConflict>& conflicts=pDoc->GetCdlConfig()->get_all_conflicts();
693 CFailingRulesDialog dlg(conflicts,transaction,&pDoc->m_arConflictsOfInterest);
694 rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
695 pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
700 CdlInferenceCallbackResult CConfigToolDoc::CdlInferenceHandler (CdlTransaction transaction)
702 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
703 CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
704 const std::list<CdlConflict>&conflicts=transaction->get_new_conflicts();
705 if((pDoc->m_nRuleChecking&Immediate) && conflicts.size()>0){
706 if(pDoc->m_nRuleChecking&SuggestFixes){
707 std::list<CdlConflict> s_conflicts;
708 for (std::list<CdlConflict>::const_iterator conf_i= conflicts.begin (); conf_i != conflicts.end (); conf_i++) { // for each conflict
709 if((*conf_i)->has_known_solution()){
710 s_conflicts.push_back(*conf_i);
713 if(s_conflicts.size()>0){
714 CFailingRulesDialog dlg(s_conflicts,transaction);
715 return(IDOK==dlg.DoModal()?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel);
719 if(1==conflicts.size()){
720 strMsg=(_T("There is 1 unresolved conflict."));
722 strMsg.Format(_T("There are %d unresolved conflict%s."),conflicts.size(),1==conflicts.size()?_T(""):_T("s"));
724 rc=(IDYES==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("%s Make the change anyway?"),strMsg))?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
730 // a CDL transaction handler to refresh the configuration tree
731 void CConfigToolDoc::CdlTransactionHandler (const CdlTransactionCallback & data)
733 static int nNesting=0;
734 TRACE(_T("Transaction handler: nesting level=%d\n"),nNesting++);
735 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
736 std::vector<CdlValuable>::const_iterator val_i;
737 std::vector<CdlNode>::const_iterator node_i;
738 std::list<CdlConflict>::const_iterator conf_i;
739 CControlView *pControlView=CConfigTool::GetControlView();
740 for (val_i = data.value_changes.begin(); val_i != data.value_changes.end(); val_i++)
742 const CString strName((*val_i)->get_name().c_str());
743 TRACE(_T("%s %s : value change\n"), CString ((*val_i)->get_class_name().c_str()), strName);
744 pControlView->Refresh(strName);
745 if (strName==_T("CYGHWR_MEMORY_LAYOUT")){ // the memory layout has changed...
746 pDoc->SwitchMemoryLayout (false); // ...so display a new one
749 for (node_i = data.active_changes.begin(); node_i != data.active_changes.end(); node_i++)
751 const CString strName((*node_i)->get_name().c_str());
752 TRACE(_T("%s %s : this has become active or inactive\n"), CString ((*node_i)->get_class_name().c_str()),
753 CString ((*node_i)->get_name().c_str()));
754 if (! dynamic_cast<CdlInterface> (*node_i)){ // if not an interface node
755 pControlView->Refresh(strName);
758 for (val_i = data.legal_values_changes.begin(); val_i != data.legal_values_changes.end(); val_i++)
760 const CString strName((*node_i)->get_class_name().c_str());
761 TRACE(_T("%s %s : the legal_values list has changed, a new widget may be needed.\n"),
762 CString ((*val_i)->get_class_name().c_str()), strName);
765 for (val_i = data.value_source_changes.begin(); val_i != data.value_source_changes.end(); val_i++)
767 const CString strName((*val_i)->get_name().c_str());
768 CdlValueSource source = (*val_i)->get_source();
769 TRACE(_T("%s %s : the value source has changed to %s\n"),
770 CString ((*val_i)->get_class_name().c_str()), strName,
771 CString ((CdlValueSource_Default == source) ? "default" :
772 (CdlValueSource_Inferred == source) ? "inferred" :
773 (CdlValueSource_Wizard == source) ? "wizard" : "user"));
774 pControlView->Refresh (strName);
777 pDoc->UpdateFailingRuleCount();
781 // Three hack functions.
783 const CString CConfigToolDoc::CurrentMemoryLayout ()
785 const CConfigItem * pItem = Find (_T("CYGHWR_MEMORY_LAYOUT"));
788 TRACE(_T("Warning - CurrentMemoryLayout() returning NULL\n"));
791 return pItem ? pItem->StringValue () : _T("");
794 const CString CConfigToolDoc::CurrentTestingIdentifier ()
796 // use the CDL target as the default testing identifier
797 // override in the forthcoming testing identifier dialog as necessary
798 return GetCdlConfig()->get_hardware ().c_str ();
800 // const CConfigItem * pItem = Find (_T("CYGTST_TESTING_IDENTIFIER"));
803 // TRACE(_T("Warning - CurrentTestingIdentifier() returning NULL\n"));
806 // return pItem ? pItem->StringValue () : _T("");
809 const CString CConfigToolDoc::CurrentStartup()
811 const CConfigItem * pItem = Find (_T("CYG_HAL_STARTUP"));
814 TRACE(_T("Warning - CurrentStartup() returning NULL\n"));
817 return pItem ? pItem->StringValue () : _T("");
820 for(int nItem=0;nItem<ItemCount();nItem++){
821 CConfigItem *pItem=Item(nItem);
822 const CString strName(pItem->Name());
823 if(0==strName.Compare(_T("Startup type")) && pItem->IsEnabled()){
824 return pItem->StringValue();
827 return _T("ram"); // FIXME - assume ram startup for now if no startup item
831 void CConfigToolDoc::UpdateFailingRuleCount()
834 if (GetCdlConfig ()){
835 // if configuration information
837 // calculate the number of conflicts
839 // GetCdlConfig ()->get_structural_conflicts ().size () + ignore for now
840 GetCdlConfig ()->get_all_conflicts ().size ();
842 // update the conflicts view
843 if (CConfigTool::GetRulesView ()) {
844 CConfigTool::GetRulesView ()->FillRules ();
847 if(CConfigTool::GetMain()){
848 CConfigTool::GetMain()->SetFailRulePane(nCount);
852 void CConfigToolDoc::LogConflicts (const std::list<CdlConflict> & conflicts)
854 std::list<CdlConflict>::const_iterator conf_i;
855 for (conf_i = conflicts.begin (); conf_i != conflicts.end (); conf_i++) // for each conflict
857 CString strExplain = (* conf_i)->get_explanation ().c_str (); // get the conflict explanation
858 CConfigTool::Log (CUtils::StripExtraWhitespace (strExplain)); // display the message in the output window
862 CString CConfigToolDoc::GetPackageName (const CString & strAlias)
864 const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
865 std::vector<std::string>::const_iterator package_i;
866 for (package_i = packages.begin (); package_i != packages.end (); package_i++)
868 const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
869 CString strPackageAlias = aliases [0].c_str ();
870 if (aliases.size () && (0 == strAlias.Compare (strPackageAlias)))
871 return package_i->c_str ();
876 void CConfigToolDoc::DeleteContents()
878 TRACE(_T("###DeleteContents()\n"));
880 CDocument::DeleteContents();
884 TRACE(_T("###DeleteContents done\n"));
887 void CConfigToolDoc::SelectPackages ()
889 CCdlPackagesDialog dlg;
890 // This map holds the CConfigItem pointers for the packages loaded before the dialog is invoked.
891 // We cannot use Find(), which traverses all items - potentially those that have been removed
892 CMapStringToPtr arLoadedPackages;
894 // generate the contents of the add/remove list boxes
895 const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
896 std::vector<std::string>::const_iterator package_i;
897 for (package_i = packages.begin (); package_i != packages.end (); package_i++)
899 // if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not list hardware packages
901 const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
902 CString strMacroName = package_i->c_str ();
904 // use the first alias (if any) as the package identifier
905 CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName;
906 CConfigItem * pItem = Find (strMacroName);
907 if (pItem) // if the package is loaded
909 arLoadedPackages.SetAt(strMacroName,pItem);
910 // pass the currently selected package version string to the dialog box
911 const CdlValuable valuable = pItem->GetCdlValuable();
912 dlg.Insert (strPackageName, TRUE, NULL, valuable ? (LPCTSTR) CString (valuable->get_value ().c_str ()) : NULL);
916 // pass version string of the most latest version to the dialog box
917 dlg.Insert (strPackageName, FALSE, NULL, (LPCTSTR) CString (m_CdlPkgData->get_package_versions (* package_i) [0].c_str ()));
922 if (IDOK == dlg.DoModal ())
924 bool bChanged = false; // until proved otherwise
926 // determine whether each package has changed loaded/unloaded state
927 for (package_i = packages.begin (); package_i != packages.end (); package_i++)
928 // if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not check hardware packages
930 const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
931 CString strMacroName = package_i->c_str ();
933 // use the first alias (if any) as the package identifier
934 CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName;
936 CConfigItem *pItem=NULL;
937 bool bPreviouslyLoaded=arLoadedPackages.Lookup(strMacroName,(void *&)pItem);
938 bool bNowLoaded=dlg.IsAdded (strPackageName);
940 // unload packages which are no longer required before
941 // loading new ones to avoid potential duplicate macro definitions
942 if (! bNowLoaded && bPreviouslyLoaded){
943 // The package was loaded but should now be unloaded:
944 bChanged|=pItem->Unload();
945 } else if (bNowLoaded) {// if the package should be loaded
946 const CString strVersion(dlg.GetVersion (strPackageName));
947 if (bPreviouslyLoaded) { // if the package is already loaded
948 CdlTransactionCallback::set_callback_fn (NULL); // avoid value refresh attempts during load/unload
949 bChanged|=pItem->ChangeVersion(strVersion);
950 CdlTransactionCallback::set_callback_fn (CdlTransactionHandler); // restore value refresh
952 // the package was not loaded but should now be loaded
953 TRACE (_T("Loading package %s\n"), strMacroName);
956 GetCdlConfig()->load_package (CUtils::UnicodeToStdStr(strMacroName), CUtils::UnicodeToStdStr (strVersion), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
959 catch (CdlStringException exception)
961 CUtils::MessageBoxF(_T("Error loading package %s:\n\n%s"), strMacroName, CString (exception.get_message ().c_str ()));
965 CUtils::MessageBoxF(_T("Error loading package %s."), strMacroName);
971 if (bChanged) {// at least one package was loaded, unloaded or changed version
978 bool CConfigToolDoc::SetValue(CConfigItem &ti,ItemIntegerType nValue, CdlTransaction transaction/*=NULL*/)
981 case CConfigItem::Enum:
982 case CConfigItem::Integer:
983 // case CConfigItem::Boolean:
984 // case CConfigItem::Radio:
986 case CConfigItem::None:
987 case CConfigItem::String:
994 bool bChangingMemmap=MemoryMap.map_modified () && ((ti.Macro ().Compare (_T ("CYG_HAL_STARTUP")) == 0));
996 if(nValue==ti.Value()){
1000 // test if the new integer value is in range
1001 if (CConfigItem::Integer == ti.Type ())
1003 const CdlValuable valuable = ti.GetCdlValuable();
1004 CdlListValue list_value;
1005 CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
1006 valuable->get_legal_values ()->eval (context, list_value);
1007 if (! list_value.is_member ((cdl_int) nValue))
1009 if (nValue==(ItemIntegerType) valuable->get_integer_value (CdlValueSource_Current) || IDNO == CUtils::MessageBoxFT (MB_YESNO, _T("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
1010 CUtils::IntToStr (nValue, CConfigTool::GetConfigToolDoc ()->m_bHex), ti.Macro ()))
1015 // if(!ti.CanSetValue(nValue))
1017 // if(bInteractive){
1018 // CString strExplanation;
1019 // if(CConfigItem::Integer==ti.Type()){
1020 // strExplanation.Format(_T(" [value must lie in the range %d..%d]"),
1021 // CUtils::IntToStr(ti.Min(),m_bHex),
1022 // CUtils::IntToStr(ti.Max()),m_bHex);
1024 // CUtils::MessageBoxF(
1025 // _T("Cannot set '%s' to %s%s"),
1026 // ti.ItemNameOrMacro(), CUtils::IntToStr(nValue,m_bHex), strExplanation);
1031 // warn the user if the current memory layout has been changed and will be lost
1032 // this will happen when the layout has been modified and the target-platform-startup is changed
1034 if (bChangingMemmap && IDCANCEL==CUtils::MessageBoxFT(MB_OKCANCEL,_T("Changes to the current memory layout will be lost."))){
1039 if(!ti.SetValue(nValue,transaction)){
1040 // CanSetValue above should have caught this
1041 CUtils::MessageBoxF(_T("Cannot set '%s' to %d"),ti.ItemNameOrMacro(), nValue);
1049 UpdateFailingRuleCount ();
1050 UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti);
1051 // switch to new memory layout when target, platform or startup changes
1052 // but ignore cases where a target or platform is being deactivated (PR 19363)
1054 // if (((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform) || (ti.Name ().Compare (_T ("Startup type")) == 0)) &&
1055 // ((ti.Type () != CConfigItem::Radio) || (nValue)))
1056 // SwitchMemoryLayout ((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform));
1061 bool CConfigToolDoc::OpenRepository(LPCTSTR pszRepository/*=NULL*/,bool bPromptInitially/*=false*/)
1063 if(!m_bRepositoryOpen){
1065 CIdleMessage IM(_T("Opening repository"));
1066 UpdateFailingRuleCount();
1068 CFileName strNewRepository;
1069 while(!m_bRepositoryOpen){
1071 if(bPromptInitially){
1072 CFolderDialog dlg(/*BOOL bAllowCreation=*/false);
1073 dlg.m_strDesc=_T("Please specify the root of the eCos repository tree.");
1074 dlg.m_strTitle=_T("Choose folder for eCos repository");
1075 dlg.m_strFolder=strNewRepository;
1076 CConfigTool::DismissSplash();
1077 if(IDCANCEL==dlg.DoModal()){
1080 strNewRepository=dlg.m_strFolder;
1082 // Use what came in as parameter or what was found in registry
1083 strNewRepository=pszRepository?pszRepository:m_strRepository;
1084 bPromptInitially=true;
1087 IM.Set (_T("Opening repository ") + (CString) strNewRepository);
1089 CdlPackagesDatabase NewCdlPkgData = NULL;
1090 CdlInterpreter NewCdlInterp = NULL;
1091 CdlConfiguration NewCdlConfig = NULL;
1092 CFileName strNewPackagesDir;
1094 EnableCallbacks(false); // disable transaction callbacks until the config tree is regenerated
1096 if(OpenRepository(strNewRepository,NewCdlPkgData,NewCdlInterp,NewCdlConfig,strNewPackagesDir)){
1099 // select the "default" template if it exists
1100 // otherwise select the first available template
1101 std::string default_template = "default";
1102 if (! NewCdlPkgData->is_known_template (default_template))
1104 const std::vector<std::string>& templates = NewCdlPkgData->get_templates ();
1105 if (templates.size () != 0)
1106 default_template = templates [0];
1109 m_template_version = "";
1112 const std::vector<std::string>& template_versions = NewCdlPkgData->get_template_versions (default_template);
1113 NewCdlConfig->set_template (default_template, template_versions [0], &CdlParseErrorHandler, &CdlParseWarningHandler);
1114 m_template_version = template_versions [0];
1116 catch (CdlStringException exception) {
1117 CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (default_template.c_str ()), CString (exception.get_message ().c_str ()));
1120 CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (default_template.c_str ()));
1123 // check the configuration
1124 ASSERT (NewCdlConfig->check_this (cyg_extreme));
1126 // use the new package database, interpreter and configuration
1127 deleteZ(m_CdlConfig); // delete the previous configuration
1128 deleteZ(m_CdlInterp); // delete the previous interpreter
1129 deleteZ(m_CdlPkgData); // delete the previous package database
1131 m_CdlPkgData = NewCdlPkgData;
1132 m_CdlInterp = NewCdlInterp;
1133 m_CdlConfig = NewCdlConfig;
1135 // save the repository location
1137 SetRepository(strNewRepository);
1138 m_strPackagesDir = strNewPackagesDir;
1141 // clear the previously specified document file name (if any),
1142 // OnNewDocument() calls DeleteContents() so must be called
1143 // before AddAllItems()
1144 CDocument::OnNewDocument ();
1147 // generate the CConfigItems from their CDL descriptions
1150 m_bRepositoryOpen=true;
1153 deleteZ(NewCdlConfig);
1154 deleteZ(NewCdlInterp);
1155 deleteZ(NewCdlPkgData);
1159 // install a transaction handler callback function now that the tree exists
1160 EnableCallbacks(true);
1164 return m_bRepositoryOpen;
1167 // Helper fn for namesake above
1168 bool CConfigToolDoc::OpenRepository (const CFileName strNewRepository,CdlPackagesDatabase &NewCdlPkgData,CdlInterpreter &NewCdlInterp,CdlConfiguration &NewCdlConfig,CFileName &strNewPackagesDir)
1171 TRACE(_T("###Open repository %s\n"),strNewRepository);
1172 if(!strNewRepository.IsEmpty()){
1173 // Now strNewRepository is guaranteed non-empty, but does it exist?
1174 if(!strNewRepository.IsDir()) {
1175 CUtils::MessageBoxF(_T("Cannot open repository - the folder %s does not exist"), strNewRepository);
1178 // Ok so it exists, but does it look right?
1179 strNewPackagesDir=strNewRepository+_T("ecc");
1180 if(!strNewPackagesDir.IsDir()){
1181 strNewPackagesDir=strNewRepository+_T("packages");
1184 if(!strNewPackagesDir.IsDir()){
1185 // Don't mention the ecc\ attempt
1186 CUtils::MessageBoxF(_T("%s does not seem to be a source repository: the folder %s does not exist"),
1187 strNewRepository,strNewPackagesDir);
1190 const CFileName strDatabase = strNewPackagesDir + _T("ecos.db");
1191 if(!strDatabase.Exists()) {
1192 CUtils::MessageBoxF(_T("%s does not seem to be a source repository: %s does not exist"), strNewRepository, strDatabase);
1195 // create a CDL repository, interpreter and configuration
1197 try {// create a new package database, interpreter and configuration
1198 NewCdlPkgData = CdlPackagesDatabaseBody::make (CUtils::UnicodeToStdStr(strNewPackagesDir), &CdlParseErrorHandler, &CdlParseWarningHandler);
1199 NewCdlInterp = CdlInterpreterBody::make ();
1200 NewCdlConfig = CdlConfigurationBody::make ("eCos", NewCdlPkgData, NewCdlInterp);
1202 catch (CdlStringException exception) {
1203 CUtils::MessageBoxF(_T("Error opening eCos repository:\n\n%s"), CString (exception.get_message ().c_str ()));
1207 CUtils::MessageBoxF(_T("Error opening eCos repository."));
1211 // select the default target if specified in the registry
1212 // otherwise select the first available target
1213 std::string default_hardware = CUtils::UnicodeToStdStr (GetDefaultHardware ());
1214 if (! NewCdlPkgData->is_known_target (default_hardware)) {
1215 const std::vector<std::string>& targets = NewCdlPkgData->get_targets ();
1216 if (targets.size () == 0){
1217 CUtils::MessageBoxF (_T("Error opening eCos repository:\n\nno hardware templates"));
1220 default_hardware = targets [0];
1225 m_strCdlErrorMessage = _T("");
1226 NewCdlConfig->set_hardware (default_hardware, &CdlParseErrorHandler, &CdlParseWarningHandler);
1228 catch (CdlStringException exception) {
1229 if (m_strCdlErrorMessage.IsEmpty ())
1231 CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), CString (exception.get_message ().c_str ()));
1233 else // report the most recent parser message in the message box since there may be no output pane in which to view it
1235 CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s\n\nParser message:\n\n%s"), CString (default_hardware.c_str ()), CString (exception.get_message ().c_str ()), m_strCdlErrorMessage);
1240 CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), m_strCdlErrorMessage);
1251 void CConfigToolDoc::CloseRepository()
1253 if(m_bRepositoryOpen){
1254 // delete the libCDL objects with the document
1255 EnableCallbacks(false); // first disable the transaction handler
1256 deleteZ(m_CdlConfig);
1257 deleteZ(m_CdlInterp);
1258 deleteZ(m_CdlPkgData);
1259 m_bRepositoryOpen=false;
1263 void CConfigToolDoc::SelectTemplate (std::string NewTemplate, std::string NewTemplateVersion)
1265 if ((NewTemplate != m_CdlConfig->get_template()) || (NewTemplateVersion != m_template_version)){
1267 CWaitCursor wait; // this may take a little while
1269 m_template_version = "";
1272 m_CdlConfig->set_template (NewTemplate, NewTemplateVersion, CdlParseErrorHandler, CdlParseWarningHandler);
1273 m_template_version = NewTemplateVersion;
1275 catch (CdlStringException exception)
1277 CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ()));
1281 CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (NewTemplate.c_str ()));
1285 if (!GetPathName().IsEmpty()){ // not a new document
1286 CopyMLTFiles (); // copy new MLT files to the build tree as necessary
1292 void CConfigToolDoc::RegenerateData()
1294 CWaitCursor wait; // This may take a little while
1295 AddAllItems (); // regenerate all the config items since the topology may have changed
1296 if (m_strLinkerScriptFolder.IsEmpty ())
1298 CUtils::MessageBoxF(_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."));
1300 if (m_strMemoryLayoutFolder.IsEmpty ())
1302 CUtils::MessageBoxF(_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."));
1304 SwitchMemoryLayout (true); // the hardware template may have changed
1306 CConfigTool::GetControlView()->SelectItem(Item(0));
1309 void CConfigToolDoc::SelectHardware (std::string NewTemplate)
1311 const std::string OldTemplate=m_CdlConfig->get_hardware();
1312 if (NewTemplate != OldTemplate){
1317 m_CdlConfig->set_hardware (NewTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1319 catch (CdlStringException exception)
1321 CUtils::MessageBoxF(_T("Error loading hardware template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ()));
1322 m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1326 CUtils::MessageBoxF(_T("Error loading hardware template '%s'."), CString (NewTemplate.c_str ()));
1327 m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1331 //EnableCallbacks(true); // re-enable the transaction handler
1332 if (!GetPathName().IsEmpty()){
1333 CopyMLTFiles (); // copy new MLT files to the build tree as necessary
1339 bool CConfigToolDoc::SaveMemoryMap()
1341 const CString strSuffix(_T("mlt_") + CurrentMemoryLayout ());
1342 const CFileName strMLTInstallPkgconfDir(InstallTree() + _T("include\\pkgconf"));
1344 if(strMLTInstallPkgconfDir.CreateDirectory(true)){
1345 const CString strMLTInstallBase(strMLTInstallPkgconfDir+CFileName(strSuffix));
1346 const CFileName strMLTDir (MLTDir());
1347 if(strMLTDir.CreateDirectory (true)){
1348 const CString strMLTBase (strMLTDir + CFileName (strSuffix));
1349 TRACE(_T("Saving memory layout to %s\n"), strMLTBase + _T(".mlt"));
1350 if(MemoryMap.save_memory_layout (strMLTBase + _T(".mlt"))){
1351 TRACE(_T("Exporting memory layout to %s\n"), strMLTInstallPkgconfDir);
1352 rc=MemoryMap.export_files (strMLTInstallBase + _T(".ldi"), strMLTInstallBase + _T(".h"));
1359 bool CConfigToolDoc::CopyMLTFiles()
1361 // copy default MLT files for the selected target/platform from the repository if they do not already exist
1363 TRACE (_T("Looking for MLT files at %s\n"), PackagesDir() + m_strMemoryLayoutFolder + _T("include\\pkgconf\\mlt_*.*"));
1364 const CFileName strInstallDestination(InstallTree () + _T("include\\pkgconf"));
1365 const CFileName strMLTDestination (MLTDir ());
1366 TRACE (_T("Copying .ldi and .h files to %s\n"), strInstallDestination);
1367 TRACE (_T("Copying .mlt files to %s\n"), strMLTDestination);
1368 bool rc=strInstallDestination.CreateDirectory (true) && strMLTDestination.CreateDirectory (true);
1370 CFileFind ffFileFind;
1371 BOOL bLastFile = ffFileFind.FindFile (PackagesDir() + m_strMemoryLayoutFolder + _T("\\include\\pkgconf\\mlt_*.*"));
1374 bLastFile = ffFileFind.FindNextFile ();
1375 if (_T(".mlt") == ffFileFind.GetFileName ().Right (4)) // if a .mlt file
1377 if (! CFileName (strMLTDestination, CFileName (ffFileFind.GetFileName ())).Exists ())
1379 if(!CUtils::CopyFile (ffFileFind.GetFilePath (), strMLTDestination + CFileName (ffFileFind.GetFileName ()))){
1380 return false; // message already emitted
1384 else // a .h or .ldi file
1386 if (! CFileName (strInstallDestination, CFileName (ffFileFind.GetFileName ())).Exists () &&
1387 !CUtils::CopyFile (ffFileFind.GetFilePath (), strInstallDestination + CFileName (ffFileFind.GetFileName ()))){
1388 return false; // message already emitted
1396 CString CConfigToolDoc::GetDefaultHardware ()
1398 CString strKey = _T("SOFTWARE\\Red Hat\\eCos");
1399 CString strVersionKey = _T("");
1400 CString rc = _T("");
1401 TCHAR pszBuffer [MAX_PATH + 1];
1405 // get the greatest eCos version subkey
1406 if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey))
1409 while (ERROR_SUCCESS == RegEnumKey (hKey, dwIndex++, (LPTSTR) pszBuffer, sizeof (pszBuffer)))
1411 if (strVersionKey.Compare (pszBuffer) < 0)
1412 strVersionKey = pszBuffer;
1415 if (! strVersionKey.IsEmpty ())
1417 TRACE (_T("CConfigToolDoc::GetDefaultHardware(): version subkey = '%s'\n"), strVersionKey);
1419 // get the default hardware value
1420 strKey += _T("\\") + strVersionKey;
1421 if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey))
1423 DWORD dwBufferSize = sizeof (pszBuffer);
1424 lStatus = RegQueryValueEx (hKey, _T("Default Hardware"), NULL, NULL, (LPBYTE) pszBuffer, &dwBufferSize);
1426 if (ERROR_SUCCESS == lStatus)
1428 TRACE (_T("CConfigToolDoc::GetDefaultHardware(): default hardware = '%s'\n"), pszBuffer);
1437 CConfigItem * CConfigToolDoc::AddItem (const CdlUserVisible vitem, CConfigItem * pParent)
1439 CConfigItem * pItem = new CConfigItem (pParent, vitem);
1441 m_arItem.Add(pItem);
1442 pItem->m_strDesc = CUtils::StripExtraWhitespace (CString (vitem->get_description ().c_str ()));
1444 if (vitem->get_name () == "CYGHWR_MEMORY_LAYOUT")
1446 ASSERT (m_strMemoryLayoutFolder.IsEmpty ());
1447 m_strMemoryLayoutFolder = vitem->get_owner ()->get_directory().c_str ();
1448 m_strMemoryLayoutFolder.Replace(_TCHAR('/'),_TCHAR('\\'));
1449 TRACE (_T("Found memory layout folder: %s\n"), m_strMemoryLayoutFolder);
1452 if (vitem->get_name () == "CYGBLD_LINKER_SCRIPT")
1454 ASSERT (m_strLinkerScriptFolder.IsEmpty ());
1455 m_strLinkerScriptFolder = vitem->get_owner ()->get_directory().c_str ();
1456 m_strLinkerScriptFolder.Replace(_TCHAR('/'),_TCHAR('\\'));
1457 TRACE (_T("Found linker script folder: %s\n"), m_strLinkerScriptFolder);
1459 // the CDL hardware template name will eventually become the target name,
1460 // but for now we must deduce the target name from the linker script file name
1462 const CdlValuable valuable = dynamic_cast<CdlValuable> (vitem);
1463 CFileName strLinkerScript (m_strPackagesDir, m_strLinkerScriptFolder, CString (valuable->get_value ().c_str ()));
1464 strLinkerScript.Replace (_TCHAR('/'), _TCHAR('\\'));
1465 if(!strLinkerScript.Exists ()){
1466 CConfigTool::Log(_T("%s does not exist\n"),strLinkerScript);
1468 TRACE (_T("Target '%s' selected\n"), strLinkerScript.Tail ().Root (), pItem->Macro());
1469 //CFileName strBinDir = AfxGetApp () -> GetProfileString (CUtils::LoadString (IDS_KEY_TOOLS_DIR), pTarget->Name (), _T(""));
1470 //if (! strBinDir.IsEmpty () && strBinDir.IsDir ())
1472 // pTarget->SetBinDir (strBinDir);
1476 //TRACE(_T("Created new item from cdl: "));
1477 //pItem->DumpItem();
1481 void CConfigToolDoc::AddAllItems ()
1483 // remove any old items and packages
1485 if(NULL!=CConfigTool::GetControlView()){ // may not be the case for plugin
1487 // add the root item
1488 CConfigItem * pItem = new CConfigItem (NULL, NULL);
1489 m_arItem.Add(pItem);
1490 pItem->m_strDesc = _T("The root node for all configurable items");
1492 // add the remaining items using their CDL descriptions
1493 m_strMemoryLayoutFolder = _T("");
1494 m_strLinkerScriptFolder = _T("");
1495 AddContents (m_CdlConfig, FirstItem ());
1497 // check that exactly one radio button in each group is enabled
1500 // update the rules (conflicts) view
1501 UpdateFailingRuleCount ();
1503 if(NULL==CConfigTool::GetRulesView() || !CConfigTool::GetRulesView()->IsWindowVisible()){
1504 // log all conflicts
1505 // LogConflicts (m_CdlConfig->get_structural_conflicts ()); // relating to package availability - ignore for now
1506 LogConflicts (m_CdlConfig->get_all_conflicts ());
1509 CConfigTool::GetControlView()->SelectItem(Item(0));
1510 UpdateAllViews (NULL, SelChanged, (CObject *)Item(0)); // refresh the display
1512 CConfigTool::GetControlView()->GetTreeCtrl().Expand(Item(0)->HItem(),TVE_EXPAND);
1514 CConfigTool::GetControlView()->SetFocus();
1518 const CFileName CConfigToolDoc::CurrentLinkerScript()
1520 const CConfigItem * pItem = Find (_T("CYGBLD_LINKER_SCRIPT"));
1521 return pItem ? CFileName (m_strPackagesDir, m_strLinkerScriptFolder, pItem->StringValue ()) : _T("");
1524 bool CConfigToolDoc::GenerateHeaders()
1526 // Copy non-config header files from the repository to the
1527 // install tree for plugin only. The make system used by
1528 // the standalone config tool does this for us.
1530 typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
1531 const EntriesArray &arEntries=BuildInfo().entries;
1532 typedef std::vector<CdlBuildInfo_Header> HeaderArray;
1533 for(EntriesArray::size_type j=0;j<arEntries.size();j++){
1534 const CdlBuildInfo_Loadable &e=arEntries[j];
1535 const CFileName strDir(CUtils::WPath(e.directory));
1536 const HeaderArray &arHeaders=e.headers;
1537 for(HeaderArray::size_type i=0;i<arHeaders.size();i++){
1538 const CdlBuildInfo_Header &h=arHeaders[i];
1539 const CFileName strSource(PackagesDir()+strDir+CUtils::WPath(h.source));
1540 const CFileName strDest(HeadersDir()/*+CUtils::WPath(e.directory)*/+CUtils::WPath(h.destination));
1542 if(!strDest.Head().CreateDirectory(true)){
1543 CUtils::MessageBoxF(_T("Failed to create %s - %s"),strDest.Head(),CUtils::GetLastErrorMessageString());
1546 if(!CUtils::CopyFile(strSource,strDest)){
1547 return false; // message already emitted
1555 CFileName strPkfConfDir(InstallTree()+_T("include\\pkgconf"));
1556 if(!strPkfConfDir.CreateDirectory()){
1557 CUtils::MessageBoxF(_T("Failed to create %s - %s"),strPkfConfDir,CUtils::GetLastErrorMessageString());
1560 GetCdlConfig()->generate_config_headers(CUtils::UnicodeToStdStr(strPkfConfDir.ShortName()));
1562 catch (CdlInputOutputException e) {
1563 const CString strMsg(e.get_message().c_str());
1564 TRACE(_T("!!! Exception thrown calling generate_config_headers - %s"),strMsg);
1565 CUtils::MessageBoxF(_T("Failed to generate header files - %s"),strMsg);
1571 const CFileName CConfigToolDoc::MLTDir ()
1573 CString strPathName (GetPathName ());
1574 ASSERT (! strPathName.IsEmpty ());
1575 return strPathName.Left (strPathName.ReverseFind (_TCHAR('.'))) + _T("_mlt");
1578 bool CConfigToolDoc::UpdateBuildInfo(bool bFirstTime)
1581 GetCdlConfig()->get_build_info(m_BuildInfo);
1583 // FIXME: this means anything not mentioned by AddFile in our scan below will be removed - including user-added items
1584 m_peCosProject->ClearItemFlags();
1585 m_peCosProject->UpdateeCosProject(bFirstTime);
1586 m_peCosProject->RemoveAllUnflaggedItems();
1588 UNUSED_ALWAYS(bFirstTime);
1589 generate_build_tree (GetCdlConfig(), CUtils::UnicodeToStdStr(BuildTree()), CUtils::UnicodeToStdStr(InstallTree()));
1598 void CConfigToolDoc::RemoveAllItems()
1600 for(int nItem=0;nItem<ItemCount();nItem++){
1601 CConfigItem *pItem=Item(nItem);
1604 m_arItem.RemoveAll();
1606 UpdateAllViews(NULL,Clear,0);
1609 void CConfigToolDoc::EnableCallbacks (bool bEnable/*=true*/)
1611 CdlTransactionCallback::set_callback_fn(bEnable?&CdlTransactionHandler:0);
1612 CdlTransactionBody::set_inference_callback_fn(bEnable?&CdlInferenceHandler:0);
1613 CdlTransactionBody::set_inference_override(CdlValueSource_Invalid);
1616 int CConfigToolDoc::GetTestExeNames (CFileNameArray &arTestExes,CFileNameArray &arMissing)
1618 arTestExes.RemoveAll();
1619 arMissing.RemoveAll();
1621 typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
1622 const EntriesArray &arEntries=BuildInfo().entries;
1623 for(EntriesArray::size_type j=0;j<arEntries.size();j++){
1624 const CdlBuildInfo_Loadable &e=arEntries[j];
1626 int n=CUtils::Chop(CString(get_tests(GetCdlConfig(),e).c_str()),ar);
1627 for(int i=0;i<n;i++){
1629 strFile.Format(_T("%s\\tests\\%s\\%s.exe"),InstallTree(),CString(e.directory.c_str()),ar[i]);
1630 strFile.Replace(_TCHAR('/'),_TCHAR('\\'));
1631 if(strFile.Exists()){
1632 arTestExes.Add(strFile);
1634 arMissing.Add(strFile);
1638 return arTestExes.GetSize();
1641 CConfigToolDoc::GlobalConflictOutcome CConfigToolDoc::ResolveGlobalConflicts(CPtrArray *parConflictsOfInterest)
1643 m_ConflictsOutcome=NotDone;
1644 m_arConflictsOfInterest.RemoveAll();
1645 if(parConflictsOfInterest){
1646 m_arConflictsOfInterest.Copy(*parConflictsOfInterest);
1648 CdlInferenceCallback fn=CdlTransactionBody::get_inference_callback_fn();
1649 CdlTransactionBody::set_inference_callback_fn(CdlGlobalInferenceHandler);
1650 GetCdlInterpreter()->get_toplevel()->resolve_all_conflicts();
1651 CdlTransactionBody::set_inference_callback_fn(fn);
1652 if(NotDone==m_ConflictsOutcome){
1653 // No solutions were available, but we'll run the dialog anyway
1654 const std::list<CdlConflict>& conflicts=GetCdlConfig()->get_all_conflicts();
1655 CFailingRulesDialog dlg(conflicts,NULL,&m_arConflictsOfInterest);
1656 m_ConflictsOutcome=(IDOK==dlg.DoModal())?OK:Cancel;
1658 return m_ConflictsOutcome;
1661 bool CConfigToolDoc::CheckConflictsBeforeSave()
1663 if(GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size()>0){
1664 if(Deferred&m_nRuleChecking){
1665 if((SuggestFixes&m_nRuleChecking)&&(Cancel==ResolveGlobalConflicts())){
1668 int nConflicts=GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size();
1673 if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There is 1 unresolved conflict. Save anyway?"))){
1677 if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There are %d unresolved conflicts. Save anyway?"),nConflicts)){
1686 BOOL CConfigToolDoc::IsModified()
1688 return m_bModified || MemoryMap.map_modified();
1691 void CConfigToolDoc::OnFileExport()
1693 CFileDialog dlg (FALSE, _T("ecm"), NULL, OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configuration (*.ecm)|*.ecm||"), AfxGetMainWnd ());
1694 TCHAR szBuffer [MAX_PATH * 16] = _T("");
1695 dlg.m_ofn.lpstrFile = szBuffer;
1696 dlg.m_ofn.nMaxFile = MAX_PATH * 16;
1697 dlg.m_ofn.lpstrTitle = _T("Export eCos Minimal Configuration");
1698 if (IDOK == dlg.DoModal ()) {
1700 TRACE (_T("Exporting eCos minimal configuration '%s'\n"), dlg.GetPathName ());
1701 m_CdlConfig->save (CUtils::UnicodeToStdStr (dlg.GetPathName ()), /* minimal = */ true);
1703 catch (CdlStringException exception) {
1704 CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ()));
1707 CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration."));
1712 void CConfigToolDoc::OnFileImport()
1714 CFileDialog dlg (TRUE, _T("ecm"), NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configurations (*.ecm)|*.ecm||"), AfxGetMainWnd ());
1715 TCHAR szBuffer [MAX_PATH * 16] = _T("");
1716 dlg.m_ofn.lpstrFile = szBuffer;
1717 dlg.m_ofn.nMaxFile = MAX_PATH * 16;
1718 dlg.m_ofn.lpstrTitle = _T("Import eCos Minimal Configuration");
1719 if (IDOK == dlg.DoModal ()) {
1721 TRACE (_T("Importing eCos minimal configuration '%s'\n"), dlg.GetPathName ());
1722 m_CdlConfig->add (CUtils::UnicodeToStdStr (dlg.GetPathName ()), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
1724 catch (CdlStringException exception) {
1725 CUtils::MessageBoxF (_T("Error importing eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ()));
1728 CUtils::MessageBoxF (_T("Error importing eCos minimal configuration."));
1732 AddAllItems (); // regenerate all the config items since the topology may have changed
1733 if (m_strLinkerScriptFolder.IsEmpty ()) {
1734 CUtils::MessageBoxF (_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."));
1736 if (m_strMemoryLayoutFolder.IsEmpty ()) {
1737 CUtils::MessageBoxF (_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."));
1739 SwitchMemoryLayout (true); // the hardware template may have changed
1741 CConfigTool::GetControlView()->SelectItem (Item (0));
1746 bool CConfigToolDoc::QualifyDocURL(CString &strURL)
1748 if(-1==strURL.Find(_T("://"))){
1749 strURL.Replace(_TCHAR('/'),_TCHAR('\\'));
1750 if (! CFileName (strURL).IsFile ()) { // if not an absolute filepath
1751 strURL = DocBase () + CFileName (strURL); // prepend the doc directory path
1753 strURL=_T("file://")+strURL;
1756 if(0==strURL.Find(_T("file://"))){
1757 CFileName strFile(strURL.Right(strURL.GetLength()-7));
1758 int nIndex=strFile.ReverseFind(_TCHAR('#'));
1760 strFile=strFile.Left(nIndex);
1762 strFile.Replace(_TCHAR('/'),_TCHAR('\\'));
1763 if(!strFile.Exists()){
1764 CUtils::MessageBoxF(_T("Cannot locate the file %s"),strFile);
1771 bool CConfigToolDoc::NewMemoryLayout (const CString &strPrefix)
1773 CFileName strFileName = CurrentLinkerScript ();
1774 TRACE(_T("Reading linker-defined memory sections from %s\n"), strFileName);
1775 MemoryMap.new_memory_layout (); // delete the old memory layout regardless
1776 if (! strFileName.IsEmpty ())
1777 MemoryMap.import_linker_defined_sections (strFileName); // read the linker-defined section names from the repository (failure is silent)
1779 CString strMemoryLayoutFileName = strPrefix + _T("\\mlt_") + CurrentMemoryLayout () + _T(".mlt");
1780 TRACE(_T("Reading memory layout from %s\n"), strMemoryLayoutFileName);
1781 MemoryMap.load_memory_layout (strMemoryLayoutFileName); // load the new memory layout (failure is silent)
1782 strSelectedSection = _T("");
1783 strSelectedRegion = _T("");
1784 UpdateAllViews (NULL, MemLayoutChanged);
1785 return true; // FIXME
1788 void CConfigToolDoc::SetPathName( LPCTSTR pszPath, BOOL bAddToMRU /*= TRUE*/ )
1790 if(_TCHAR('\0')==*pszPath){ // called like this after failed saves to put things back as they were
1791 // CDocument::SetPathName would assert given an empty string
1792 m_strPathName = _T("");
1794 SetTitle(_T("Untitled"));
1796 m_strBuildTree = _T("");
1797 m_strInstallTree = _T("");
1800 m_strPathName = CFileName (pszPath);
1802 CDocument::SetPathName (pszPath, bAddToMRU);
1804 CString strFolder (pszPath);
1805 strFolder = strFolder.Left (strFolder.ReverseFind (_TCHAR('.'))); // extract folder from file path
1806 m_strBuildTree = CFileName(strFolder + _T("_build"));
1807 m_strInstallTree = CFileName(strFolder + _T("_install"));
1811 bool CConfigToolDoc::ShowHtmlHelp (LPCTSTR pszURL)
1814 HWND hwndCaller=AfxGetMainWnd()->CWnd::GetDesktopWindow()->GetSafeHwnd();
1816 const CFileName strFile(HTMLHelpLinkFileName());
1818 if(!CFileName(CConfigTool::strHelpFile).Exists()) {
1819 CUtils::MessageBoxF(_T("Cannot display help - %s does not exist\n"),CConfigTool::strHelpFile);
1820 } else if(!f.Open(strFile,CFile::typeText|CFile::modeCreate|CFile::modeWrite)){
1821 CUtils::MessageBoxF(_T("Cannot display help - error creating %s\n"),strFile);
1824 str.Format(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"),pszURL);
1827 if(0==HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_DISPLAY_TOPIC, 0)){
1828 CUtils::MessageBoxF(_T("Cannot display %s"),pszURL);
1830 // FIXME: Do this the first time only?
1833 HH_WINTYPE *pWinType=NULL;
1834 wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile+_T(">mainwin"), HH_GET_WIN_TYPE, (DWORD) &pWinType);
1836 WinType.hwndCaller=hwndCaller;
1837 WinType.fsWinProperties|=HHWIN_PROP_TRACKING;
1838 WinType.idNotify = ID_HHNOTIFICATION;
1839 wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_SET_WIN_TYPE, (DWORD) &WinType);
1842 //::DeleteFile(strFile);
1847 const CString CConfigToolDoc::HTMLHelpLinkFileName()
1849 return CFileName(CConfigTool::strHelpFile).Head()+"link2.htm";