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####
26 //===========================================================================
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
35 // Description: This is a collection of utility functions.
42 //####DESCRIPTIONEND####
44 //===========================================================================
48 #include <float.h> // for DBL_DIG macro
49 #include <sys/types.h>
52 #define INCLUDEFILE <string>
53 #include "IncludeSTL.h"
55 // Chop str into pieces, using cSep as separator.
56 // " and \ have usual semantics
57 // Return value is array of pieces found.
59 int CUtils::Chop(LPCTSTR psz,CStringArray &ar,TCHAR cSep,bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/)
61 if(_TCHAR(' ')==cSep){
62 return Chop(psz,ar,_T("\t\n\v\f\r "),bObserveStrings,bBackslashQuotes);
64 ASSERT(_TCHAR('\0')!=cSep);
65 TCHAR c[2]={cSep,_TCHAR('\0')};
66 return Chop(psz,ar,c,bObserveStrings,bBackslashQuotes);
70 int CUtils::Chop(LPCTSTR psz,CStringArray &ar,LPCTSTR pszSep,bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/)
75 // Skip multiple separators
76 while(*psz&&_tcschr(pszSep,*psz)){
86 if(*psz==_TCHAR('\\') && bBackslashQuotes && psz[1]){
89 } else if(*psz==_TCHAR('"')){
91 } else if (!bInString && *psz && NULL!=_tcschr(pszSep,*psz)) {
101 } while (*psz && !_tcschr(pszSep,*psz));
102 strTok=CString(pszStart,psz-pszStart);
104 ar.SetAtGrow(i++,strTok);
110 // vararg-style message box formatter
111 int CUtils::MessageBoxF (LPCTSTR pszFormat, ...)
115 va_start(args, pszFormat);
116 rc=CUtils::vMessageBox(MB_OK, pszFormat,args);
121 // As above, but with type as first parameter.
122 int CUtils::MessageBoxFT (UINT nType, LPCTSTR pszFormat, ...)
126 va_start(args, pszFormat);
127 rc=CUtils::vMessageBox(nType, pszFormat,args);
132 int CUtils::vMessageBox(UINT nType, LPCTSTR pszFormat, va_list marker)
135 for(int nLength=100;nLength;) {
136 TCHAR *buf=new TCHAR[1+nLength];
137 int n=_vsntprintf(buf, nLength, pszFormat, marker );
139 nLength*=2; // NT behavior
140 } else if (n<nLength){
141 rc=AfxMessageBox(buf,nType);
142 nLength=0; // trigger exit from loop
144 nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
152 BOOL CUtils::StrToItemIntegerType(const CString & str,__int64 &d)
158 BOOL bHex=(str.GetLength()>2 && str[0]==_TCHAR('0') && (str[1]==_TCHAR('x')||str[1]==_TCHAR('X')));
159 d=_tcstol(str,&pEnd,bHex?16:10);
160 rc=(0==errno && (*pEnd==_TCHAR('\0')));
164 const CString CUtils::IntToStr(__int64 d,bool bHex)
167 s.Format(bHex?_T("0x%08x"):_T("%d"),d);
171 const CString CUtils::DoubleToStr (double dValue)
174 s.Format (_T("%.*e"), DBL_DIG, dValue);
178 BOOL CUtils::StrToDouble (const CString & strValue, double &dValue)
183 dValue = _tcstod (strValue, &pEnd);
184 return (0 == errno) && (*pEnd == _TCHAR('\0'));
187 const CString CUtils::Explanation(CFileException & exc)
191 case CFileException::none: strMsg=_T("No error occurred.");break;
192 case CFileException::generic: strMsg=_T(" An unspecified error occurred.");break;
193 case CFileException::fileNotFound: strMsg=_T(" The file could not be located.");break;
194 case CFileException::badPath: strMsg=_T(" All or part of the path is invalid.");break;
195 case CFileException::tooManyOpenFiles: strMsg=_T(" The permitted number of open files was exceeded.");break;
196 case CFileException::accessDenied: strMsg=_T(" The file could not be accessed.");break;
197 case CFileException::invalidFile: strMsg=_T(" There was an attempt to use an invalid file handle.");break;
198 case CFileException::removeCurrentDir: strMsg=_T(" The current working directory cannot be removed.");break;
199 case CFileException::directoryFull: strMsg=_T(" There are no more directory entries.");break;
200 case CFileException::badSeek: strMsg=_T(" There was an error trying to set the file pointer.");break;
201 case CFileException::hardIO: strMsg=_T(" There was a hardware error.");break;
202 case CFileException::sharingViolation: strMsg=_T(" SHARE.EXE was not loaded, or a shared region was locked.");break;
203 case CFileException::lockViolation: strMsg=_T(" There was an attempt to lock a region that was already locked.");break;
204 case CFileException::diskFull: strMsg=_T(" The disk is full.");break;
205 case CFileException::endOfFile: strMsg=_T(" The end of file was reached. ");break;
207 strMsg=_T(" Unknown cause");
214 const CString CUtils::LoadString(UINT id)
221 bool CUtils::AddToPath(const CFileName & strFolder, bool bAtFront)
223 CString strPath,strOldPath;
224 int nSize=GetEnvironmentVariable(_T("PATH"), NULL, 0);
226 GetEnvironmentVariable(_T("PATH"),strOldPath.GetBuffer(1+nSize),nSize);
227 strOldPath.ReleaseBuffer();
228 // Place the user tools folders at the head or tail of the new path
230 strPath.Format(_T("%s;%s"),strFolder.ShortName(),strOldPath);
232 strPath.Format(_T("%s;%s"),strOldPath,strFolder.ShortName());
238 return TRUE==::SetEnvironmentVariable(_T("PATH"),strPath);
243 CString CUtils::GetLastErrorMessageString()
248 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
251 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
257 // Display the string.
266 bool CUtils::Launch(const CFileName &strFileName, const CFileName &strViewer)
270 if(!strViewer.IsEmpty())//use custom editor
272 CString strCmdline(strViewer);
274 PTCHAR pszCmdLine=strCmdline.GetBuffer(strCmdline.GetLength());
275 GetShortPathName(pszCmdLine,pszCmdLine,strCmdline.GetLength());
276 strCmdline.ReleaseBuffer();
278 strCmdline+=_TCHAR(' ');
279 strCmdline+=strFileName;
280 PROCESS_INFORMATION pi;
283 si.cb = sizeof(STARTUPINFO);
284 si.lpReserved = NULL;
285 si.lpReserved2 = NULL;
293 //strCmdline.GetBuffer(strCmdline.GetLength()), // command line
294 strCmdline.GetBuffer(strCmdline.GetLength()), // command line
295 NULL, // process security
296 NULL, // thread security
297 TRUE, // inherit handles
303 CloseHandle(pi.hProcess);
304 CloseHandle(pi.hThread);
307 MessageBoxF(_T("Failed to invoke %s.\n"),strCmdline);
309 strCmdline.ReleaseBuffer();
310 } else {// Use association
311 TCHAR szExe[MAX_PATH];
312 HINSTANCE h=FindExecutable(strFileName,_T("."),szExe);
316 case 0: str=_T("The system is out of memory or resources.");break;
317 case 31: str=_T("There is no association for the specified file type.");break;
318 case ERROR_FILE_NOT_FOUND: str=_T("The specified file was not found.");break;
319 case ERROR_PATH_NOT_FOUND: str=_T("The specified path was not found.");break;
320 case ERROR_BAD_FORMAT: str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).");break;
323 MessageBoxF(_T("Failed to open document %s.\r\n%s"),strFileName,str);
326 SHELLEXECUTEINFO sei = {sizeof(sei), 0, AfxGetMainWnd()->GetSafeHwnd(), _T("open"),
327 strFileName, NULL, NULL, SW_SHOWNORMAL, AfxGetInstanceHandle( )};
330 HINSTANCE hInst=ShellExecute(AfxGetMainWnd()->GetSafeHwnd(),_T("open"), strFileName, NULL, _T("."), 0)/*ShellExecuteEx(&sei)*/;
331 if(int(hInst)<=32/*sei.hInstApp==0*/)
336 case 0 : str=_T("The operating system is out of memory or resources. ");break;
337 case ERROR_FILE_NOT_FOUND : str=_T("The specified file was not found. ");break;
338 case ERROR_PATH_NOT_FOUND : str=_T("The specified path was not found. ");break;
339 case ERROR_BAD_FORMAT : str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image). ");break;
340 case SE_ERR_ACCESSDENIED : str=_T("The operating system denied access to the specified file. ");break;
341 case SE_ERR_ASSOCINCOMPLETE : str=_T("The filename association is incomplete or invalid. ");break;
342 case SE_ERR_DDEBUSY : str=_T("The DDE transaction could not be completed because other DDE transactions were being processed. ");break;
343 case SE_ERR_DDEFAIL : str=_T("The DDE transaction failed. ");break;
344 case SE_ERR_DDETIMEOUT : str=_T("The DDE transaction could not be completed because the request timed out. ");break;
345 case SE_ERR_DLLNOTFOUND : str=_T("The specified dynamic-link library was not found. ");break;
346 //case SE_ERR_FNF : str=_T("The specified file was not found. ");break;
347 case SE_ERR_NOASSOC : str=_T("There is no application associated with the given filename extension. ");break;
348 case SE_ERR_OOM : str=_T("There was not enough memory to complete the operation. ");break;
349 //case SE_ERR_PNF : str=_T("The specified path was not found. ");break;
350 case SE_ERR_SHARE : str=_T("A sharing violation occurred. ");break;
351 default: str=_T("An unexpected error occurred");break;
353 MessageBoxF(_T("Failed to open document %s using %s.\r\n%s"),strFileName,szExe,str);
362 void CUtils::UnicodeToCStr(LPCTSTR str,char *&psz)
364 int nLength=1+_tcslen(str);
365 psz=new char[nLength];
367 WideCharToMultiByte(CP_ACP, 0, str, -1, psz, nLength, NULL, NULL);
373 std::string CUtils::UnicodeToStdStr(LPCTSTR str)
377 UnicodeToCStr(str,psz);
378 stdstr=std::string(psz);
383 // CUtils::StripExtraWhitespace() returns a modified version of
384 // a string in which each sequence of whitespace characters is
385 // replaced by a single space
387 CString CUtils::StripExtraWhitespace (const CString & strInput)
390 LPTSTR o=strOutput.GetBuffer(1+strInput.GetLength());
391 for(LPCTSTR c=strInput;*c;c++){
394 if (_istspace(c[1])){
395 for(c=c+2;_istspace(*c);c++);
403 strOutput.ReleaseBuffer();
404 strOutput.TrimLeft();
405 strOutput.TrimRight();
409 CFileName CUtils::WPath(const std::string &str)
411 // Convert a path as read from cdl into host format
412 // Change / to \ throughout
414 strPath(str.c_str());
415 strPath.Replace (_TCHAR('/'), _TCHAR('\\'));
419 // Copy file helper function.
420 // This makes sure the destination file is only touched as necessary.
421 // It is written using Posix calls lest it should be more broadly applicable.
423 bool CUtils::CopyFile(LPCTSTR pszSource,LPCTSTR pszDest)
425 // Compare the files. First set rc to the result of the comparison (true if the same)
429 if(-1!=_tstat(pszSource,&s1) && -1!=_tstat(pszDest,&s2) && s1.st_size==s2.st_size){
430 // Files both exist and are of equal size
431 FILE *f1=_tfopen(pszSource,_T("rb"));
433 FILE *f2=_tfopen(pszDest,_T("rb"));
438 char buf1[4096],buf2[4096];
439 nSize1=fread(buf1,1,sizeof buf1,f1);
440 nSize2=fread(buf2,1,sizeof buf2,f2);
441 if(nSize1!=nSize2 || 0!=memcmp(buf1,buf2,nSize1)){
453 // Files are identical
454 TRACE(_T("Copy not necessary: '%s' to '%s'\n"),pszSource,pszDest);
456 rc=TRUE==::CopyFile(pszSource,pszDest,FALSE);
458 TRACE(_T("Copied '%s' to '%s'\n"),pszSource,pszDest);
460 MessageBoxF(_T("Failed to copy '%s' to '%s' - %s"),pszSource,pszDest,GetLastErrorMessageString());