Mercurial > ecos-v3_0-branch
diff host/tools/Utils/win32/CTUtils.cpp @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 6736c52df507 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/Utils/win32/CTUtils.cpp @@ -0,0 +1,465 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This program is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +// +//=========================================================================== +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sdf +// Contact(s): sdf +// Date: 1998/08/11 +// Version: 0.01 +// Purpose: +// Description: This is a collection of utility functions. +// Requires: +// Provides: +// See also: +// Known bugs: +// Usage: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== +#include "stdafx.h" +#include "CTUtils.h" + +#include <float.h> // for DBL_DIG macro +#include <sys/types.h> +#include <sys/stat.h> + +#define INCLUDEFILE <string> +#include "IncludeSTL.h" + +// Chop str into pieces, using cSep as separator. +// " and \ have usual semantics +// Return value is array of pieces found. + +int CUtils::Chop(LPCTSTR psz,CStringArray &ar,TCHAR cSep,bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/) +{ + if(_TCHAR(' ')==cSep){ + return Chop(psz,ar,_T("\t\n\v\f\r "),bObserveStrings,bBackslashQuotes); + } else { + ASSERT(_TCHAR('\0')!=cSep); + TCHAR c[2]={cSep,_TCHAR('\0')}; + return Chop(psz,ar,c,bObserveStrings,bBackslashQuotes); + } +} + +int CUtils::Chop(LPCTSTR psz,CStringArray &ar,LPCTSTR pszSep,bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/) +{ + ar.RemoveAll(); + int i=0; + for(;;){ + // Skip multiple separators + while(*psz&&_tcschr(pszSep,*psz)){ + psz++; + } + if(!*psz){ + return i; + } + CString strTok; + if(bObserveStrings){ + BOOL bInString=FALSE; + do{ + if(*psz==_TCHAR('\\') && bBackslashQuotes && psz[1]){ + strTok+=psz[1]; + psz++; + } else if(*psz==_TCHAR('"')){ + bInString ^= 1; + } else if (!bInString && *psz && NULL!=_tcschr(pszSep,*psz)) { + break; + } else { + strTok+=*psz; + } + } while (*++psz); + } else { + LPCTSTR pszStart=psz; + do { + psz++; + } while (*psz && !_tcschr(pszSep,*psz)); + strTok=CString(pszStart,psz-pszStart); + } + ar.SetAtGrow(i++,strTok); + } + return ar.GetSize(); +} + + +// vararg-style message box formatter +int CUtils::MessageBoxF (LPCTSTR pszFormat, ...) +{ + int rc; + va_list args; + va_start(args, pszFormat); + rc=CUtils::vMessageBox(MB_OK, pszFormat,args); + va_end(args); + return rc; +} + +// As above, but with type as first parameter. +int CUtils::MessageBoxFT (UINT nType, LPCTSTR pszFormat, ...) +{ + int rc; + va_list args; + va_start(args, pszFormat); + rc=CUtils::vMessageBox(nType, pszFormat,args); + va_end(args); + return rc; +} + +int CUtils::vMessageBox(UINT nType, LPCTSTR pszFormat, va_list marker) +{ + int rc=0; + for(int nLength=100;nLength;) { + TCHAR *buf=new TCHAR[1+nLength]; + int n=_vsntprintf(buf, nLength, pszFormat, marker ); + if(-1==n){ + nLength*=2; // NT behavior + } else if (n<nLength){ + rc=AfxMessageBox(buf,nType); + nLength=0; // trigger exit from loop + } else { + nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length + } + delete [] buf; + } + return rc; +} + + +BOOL CUtils::StrToItemIntegerType(const CString & str,__int64 &d) +{ + extern int errno; + PTCHAR pEnd; + BOOL rc; + errno=0; + BOOL bHex=(str.GetLength()>2 && str[0]==_TCHAR('0') && (str[1]==_TCHAR('x')||str[1]==_TCHAR('X'))); + d=_tcstol(str,&pEnd,bHex?16:10); + rc=(0==errno && (*pEnd==_TCHAR('\0'))); + return rc; +} + +const CString CUtils::IntToStr(__int64 d,bool bHex) +{ + CString str; + str.Format(bHex?_T("0x%08x"):_T("%d"),d); + return str; +} + +const CString CUtils::DoubleToStr (double dValue) +{ + CString strValue; + strValue.Format (_T("%.*e"), DBL_DIG, dValue); + return strValue; +} + +BOOL CUtils::StrToDouble (const CString & strValue, double &dValue) +{ + extern int errno; + PTCHAR pEnd; + errno = 0; + dValue = _tcstod (strValue, &pEnd); + return (0 == errno) && (*pEnd == _TCHAR('\0')); +} + +const CString CUtils::Explanation(CFileException & exc) +{ + CString strMsg; + switch(exc.m_cause){ + case CFileException::none: strMsg=_T("No error occurred.");break; + case CFileException::generic: strMsg=_T(" An unspecified error occurred.");break; + case CFileException::fileNotFound: strMsg=_T(" The file could not be located.");break; + case CFileException::badPath: strMsg=_T(" All or part of the path is invalid.");break; + case CFileException::tooManyOpenFiles: strMsg=_T(" The permitted number of open files was exceeded.");break; + case CFileException::accessDenied: strMsg=_T(" The file could not be accessed.");break; + case CFileException::invalidFile: strMsg=_T(" There was an attempt to use an invalid file handle.");break; + case CFileException::removeCurrentDir: strMsg=_T(" The current working directory cannot be removed.");break; + case CFileException::directoryFull: strMsg=_T(" There are no more directory entries.");break; + case CFileException::badSeek: strMsg=_T(" There was an error trying to set the file pointer.");break; + case CFileException::hardIO: strMsg=_T(" There was a hardware error.");break; + case CFileException::sharingViolation: strMsg=_T(" SHARE.EXE was not loaded, or a shared region was locked.");break; + case CFileException::lockViolation: strMsg=_T(" There was an attempt to lock a region that was already locked.");break; + case CFileException::diskFull: strMsg=_T(" The disk is full.");break; + case CFileException::endOfFile: strMsg=_T(" The end of file was reached. ");break; + default: + strMsg=_T(" Unknown cause"); + break; + } + return strMsg; +} + + +const CString CUtils::LoadString(UINT id) +{ + CString str; + str.LoadString(id); + return str; +} + +bool CUtils::AddToPath(const CFileName & strFolder, bool bAtFront) +{ + CString strPath,strOldPath; + int nSize=GetEnvironmentVariable(_T("PATH"), NULL, 0); + if(nSize>0){ + GetEnvironmentVariable(_T("PATH"),strOldPath.GetBuffer(1+nSize),nSize); + strOldPath.ReleaseBuffer(); + // Place the user tools folders at the head or tail of the new path + if(bAtFront){ + strPath.Format(_T("%s;%s"),strFolder.ShortName(),strOldPath); + } else { + strPath.Format(_T("%s;%s"),strOldPath,strFolder.ShortName()); + } + } else { + // unlikely, but ... + strPath=strFolder; + } + return TRUE==::SetEnvironmentVariable(_T("PATH"),strPath); +} + + + +CString CUtils::GetLastErrorMessageString() +{ + CString str; + PTCHAR pszMsg; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&pszMsg, + 0, + NULL + ); + + // Display the string. + str=pszMsg; + str.TrimRight(); + // Free the buffer. + LocalFree(pszMsg); + return str; + +} + +bool CUtils::Launch(const CFileName &strFileName, const CFileName &strViewer) +{ + bool rc=false; + + if(!strViewer.IsEmpty())//use custom editor + { + CString strCmdline(strViewer); + + PTCHAR pszCmdLine=strCmdline.GetBuffer(strCmdline.GetLength()); + GetShortPathName(pszCmdLine,pszCmdLine,strCmdline.GetLength()); + strCmdline.ReleaseBuffer(); + + strCmdline+=_TCHAR(' '); + strCmdline+=strFileName; + PROCESS_INFORMATION pi; + STARTUPINFO si; + + si.cb = sizeof(STARTUPINFO); + si.lpReserved = NULL; + si.lpReserved2 = NULL; + si.cbReserved2 = 0; + si.lpDesktop = NULL; + si.dwFlags = 0; + si.lpTitle=NULL; + + if(CreateProcess( + NULL, // app name + //strCmdline.GetBuffer(strCmdline.GetLength()), // command line + strCmdline.GetBuffer(strCmdline.GetLength()), // command line + NULL, // process security + NULL, // thread security + TRUE, // inherit handles + 0, + NULL, // environment + NULL, // current dir + &si, // startup info + &pi)){ + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + rc=true; + } else { + MessageBoxF(_T("Failed to invoke %s.\n"),strCmdline); + } + strCmdline.ReleaseBuffer(); + } else {// Use association + TCHAR szExe[MAX_PATH]; + HINSTANCE h=FindExecutable(strFileName,_T("."),szExe); + if(int(h)<=32){ + CString str; + switch(int(h)){ + case 0: str=_T("The system is out of memory or resources.");break; + case 31: str=_T("There is no association for the specified file type.");break; + case ERROR_FILE_NOT_FOUND: str=_T("The specified file was not found.");break; + case ERROR_PATH_NOT_FOUND: str=_T("The specified path was not found.");break; + case ERROR_BAD_FORMAT: str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).");break; + default: break; + } + MessageBoxF(_T("Failed to open document %s.\r\n%s"),strFileName,str); + } else { + + SHELLEXECUTEINFO sei = {sizeof(sei), 0, AfxGetMainWnd()->GetSafeHwnd(), _T("open"), + strFileName, NULL, NULL, SW_SHOWNORMAL, AfxGetInstanceHandle( )}; + + sei.hInstApp=0; + HINSTANCE hInst=ShellExecute(AfxGetMainWnd()->GetSafeHwnd(),_T("open"), strFileName, NULL, _T("."), 0)/*ShellExecuteEx(&sei)*/; + if(int(hInst)<=32/*sei.hInstApp==0*/) + { + CString str; + switch(int(hInst)) + { + case 0 : str=_T("The operating system is out of memory or resources. ");break; + case ERROR_FILE_NOT_FOUND : str=_T("The specified file was not found. ");break; + case ERROR_PATH_NOT_FOUND : str=_T("The specified path was not found. ");break; + case ERROR_BAD_FORMAT : str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image). ");break; + case SE_ERR_ACCESSDENIED : str=_T("The operating system denied access to the specified file. ");break; + case SE_ERR_ASSOCINCOMPLETE : str=_T("The filename association is incomplete or invalid. ");break; + case SE_ERR_DDEBUSY : str=_T("The DDE transaction could not be completed because other DDE transactions were being processed. ");break; + case SE_ERR_DDEFAIL : str=_T("The DDE transaction failed. ");break; + case SE_ERR_DDETIMEOUT : str=_T("The DDE transaction could not be completed because the request timed out. ");break; + case SE_ERR_DLLNOTFOUND : str=_T("The specified dynamic-link library was not found. ");break; + //case SE_ERR_FNF : str=_T("The specified file was not found. ");break; + case SE_ERR_NOASSOC : str=_T("There is no application associated with the given filename extension. ");break; + case SE_ERR_OOM : str=_T("There was not enough memory to complete the operation. ");break; + //case SE_ERR_PNF : str=_T("The specified path was not found. ");break; + case SE_ERR_SHARE : str=_T("A sharing violation occurred. ");break; + default: str=_T("An unexpected error occurred");break; + } + MessageBoxF(_T("Failed to open document %s using %s.\r\n%s"),strFileName,szExe,str); + } else { + rc=true; + } + } + } + return rc; +} + +void CUtils::UnicodeToCStr(LPCTSTR str,char *&psz) +{ + int nLength=1+_tcslen(str); + psz=new char[nLength]; + #ifdef _UNICODE + WideCharToMultiByte(CP_ACP, 0, str, -1, psz, nLength, NULL, NULL); + #else + strcpy(psz,str); + #endif +} + +std::string CUtils::UnicodeToStdStr(LPCTSTR str) +{ + std::string stdstr; + char *psz; + UnicodeToCStr(str,psz); + stdstr=std::string(psz); + delete psz; + return stdstr; +} + +// CUtils::StripExtraWhitespace() returns a modified version of +// a string in which each sequence of whitespace characters is +// replaced by a single space + +CString CUtils::StripExtraWhitespace (const CString & strInput) +{ + CString strOutput; + LPTSTR o=strOutput.GetBuffer(1+strInput.GetLength()); + for(LPCTSTR c=strInput;*c;c++){ + if(_istspace(*c)){ + *o++=_TCHAR(' '); + if (_istspace(c[1])){ + for(c=c+2;_istspace(*c);c++); + c--; + } + } else { + *o++=*c; + } + } + *o=0; + strOutput.ReleaseBuffer(); + strOutput.TrimLeft(); + strOutput.TrimRight(); + return strOutput; +} + +CFileName CUtils::WPath(const std::string &str) +{ + // Convert a path as read from cdl into host format + // Change / to \ throughout + CFileName + strPath(str.c_str()); + strPath.Replace (_TCHAR('/'), _TCHAR('\\')); + return strPath; +} + +// Copy file helper function. +// This makes sure the destination file is only touched as necessary. +// It is written using Posix calls lest it should be more broadly applicable. + +bool CUtils::CopyFile(LPCTSTR pszSource,LPCTSTR pszDest) +{ + // Compare the files. First set rc to the result of the comparison (true if the same) + bool rc=false; + + struct _stat s1,s2; + if(-1!=_tstat(pszSource,&s1) && -1!=_tstat(pszDest,&s2) && s1.st_size==s2.st_size){ + // Files both exist and are of equal size + FILE *f1=_tfopen(pszSource,_T("rb")); + if(f1){ + FILE *f2=_tfopen(pszDest,_T("rb")); + if(f2){ + int nSize1,nSize2; + rc=true; + do{ + char buf1[4096],buf2[4096]; + nSize1=fread(buf1,1,sizeof buf1,f1); + nSize2=fread(buf2,1,sizeof buf2,f2); + if(nSize1!=nSize2 || 0!=memcmp(buf1,buf2,nSize1)){ + rc=false; + break; + } + } while (nSize1>0); + fclose(f2); + } + fclose(f1); + } + } + + if(rc){ + // Files are identical + TRACE(_T("Copy not necessary: '%s' to '%s'\n"),pszSource,pszDest); + } else { + rc=TRUE==::CopyFile(pszSource,pszDest,FALSE); + if(rc){ + TRACE(_T("Copied '%s' to '%s'\n"),pszSource,pszDest); + } else { + MessageBoxF(_T("Failed to copy '%s' to '%s' - %s"),pszSource,pszDest,GetLastErrorMessageString()); + } + } + + return rc; +}
