|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: YYBase.cxx
//
// Contents: Custom base class for YYPARSER
//
// History: 30-Nov-1999 KyleP Created
//
//----------------------------------------------------------------------------
#pragma hdrstop
#include "msidxtr.h"
#include "yybase.hxx"
//+-------------------------------------------------------------------------
//
// Member: CYYBase::CYYBase, public
//
// Synopsis: Constructor
//
// Arguments: [pParserSession] -- Session state
// [pParserTreeProperties] -- Command properties
// [yylex] -- Lexer
//
// History: 30-Nov-1999 KyleP Created
//
//--------------------------------------------------------------------------
CYYBase::CYYBase( CImpIParserSession* pParserSession, CImpIParserTreeProperties* pParserTreeProperties, YYLEXER & yylex ) : m_yylex( yylex ), m_pIPSession( pParserSession ), m_pIPTProperties( pParserTreeProperties ) { }
//+-------------------------------------------------------------------------
//
// Member: CYYBase::~CYYBase, public
//
// Synopsis: Destructor
//
// History: 30-Nov-1999 KyleP Created
//
//--------------------------------------------------------------------------
CYYBase::~CYYBase() { }
//+-------------------------------------------------------------------------
//
// Member: CYYBase::CoerceScalar, public
//
// Synopsis: Converts a scalar node to specified type.
//
// Arguments: [dbTypeExpected] -- Expected type
// [ppct] -- Node to convert
//
// Returns: Error if conversion not possible
//
// History: 30-Nov-1999 KyleP Moved from YYPARSER
//
//--------------------------------------------------------------------------
HRESULT CYYBase::CoerceScalar( DBTYPE dbTypeExpected, // @parm IN | DBTYPE that is expected in current context
DBCOMMANDTREE** ppct ) // @parm IN/OUT | scalar node
{ Assert( VT_I8 == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt || VT_UI8 == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt || VT_R8 == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt || VT_BSTR == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt || VT_BOOL == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt || VT_FILETIME == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt );
DBTYPE dbType = dbTypeExpected & ~DBTYPE_VECTOR;
if (DBTYPE_STR == (dbType & ~DBTYPE_BYREF)) dbType = VT_LPSTR; if (DBTYPE_WSTR == (dbType & ~DBTYPE_BYREF)) dbType = VT_LPWSTR;
HRESULT hr = (*ppct)->hrError; if (S_OK != hr) goto error; if (dbType == ((PROPVARIANT*)(*ppct)->value.pvValue)->vt) return hr;
switch ( ((PROPVARIANT*)(*ppct)->value.pvValue)->vt ) { case VT_UI8: { ULONGLONG uhVal = ((PROPVARIANT*)(*ppct)->value.pvValue)->uhVal.QuadPart; switch ( dbType ) { case VT_UI1: if (uhVal > UCHAR_MAX) hr = DISP_E_TYPEMISMATCH; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->bVal = (UCHAR)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_UI1; } break;
case VT_I1: if (uhVal > CHAR_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->cVal = (CHAR)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I1; } break;
case VT_UI2: if (uhVal > USHRT_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->uiVal = (USHORT)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_UI2; } break;
case VT_I2: if (uhVal > SHRT_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->iVal = (SHORT)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I2; } break;
case VT_UI4: if (uhVal > ULONG_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->ulVal = (ULONG)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_UI4; } break;
case VT_I4: if (uhVal > LONG_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->lVal = (LONG)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I4; } break;
case VT_I8: if (uhVal > _I64_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->hVal.QuadPart = (LONGLONG)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I8; } break;
case VT_R4: ((PROPVARIANT*)(*ppct)->value.pvValue)->fltVal = (float)(LONGLONG)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_R4; break;
case VT_R8: ((PROPVARIANT*)(*ppct)->value.pvValue)->dblVal = (double)(LONGLONG)uhVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_R8; break;
default: hr = DB_E_CANTCONVERTVALUE; } } break;
case VT_I8: { LONGLONG hVal = ((PROPVARIANT*)(*ppct)->value.pvValue)->hVal.QuadPart; switch ( dbType ) { case VT_UI1: case VT_UI2: case VT_UI4: case VT_UI8: hr = DB_E_CANTCONVERTVALUE; break;
case VT_I1: if (hVal < CHAR_MIN || hVal > CHAR_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->cVal = (CHAR)hVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I1; } break;
case VT_I2: if (hVal < SHRT_MIN || hVal > SHRT_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->iVal = (SHORT)hVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I2; } break;
case VT_I4: if (hVal < LONG_MIN || hVal > LONG_MAX) hr = DB_E_DATAOVERFLOW; else { ((PROPVARIANT*)(*ppct)->value.pvValue)->lVal = (LONG)hVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_I4; } break;
case VT_R4: ((PROPVARIANT*)(*ppct)->value.pvValue)->fltVal = (float)hVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_R4; break;
case VT_R8: ((PROPVARIANT*)(*ppct)->value.pvValue)->dblVal = (double)hVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_R8; break;
default: hr = DB_E_CANTCONVERTVALUE; } } break;
case VT_R8: switch ( dbType ) { case VT_R4: ((PROPVARIANT*)(*ppct)->value.pvValue)->fltVal = (float)((PROPVARIANT*)(*ppct)->value.pvValue)->dblVal; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_R4; break;
case VT_CY: hr = VariantChangeTypeEx( (*ppct)->value.pvarValue, // convert in place
(*ppct)->value.pvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_CY ); break;
default: hr = DB_E_CANTCONVERTVALUE; } break;
case VT_BSTR: switch ( dbType ) { case VT_R8: //
// Our syntax doesn't allow for numeric separators in other
// locales than US English. So, use the English US lcid for this
// conversion.
//
hr = VariantChangeTypeEx((*ppct)->value.pvarValue, // convert in place
(*ppct)->value.pvarValue, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, VT_R8); break;
case VT_LPSTR: { int cLen = WideCharToMultiByte( CP_ACP, 0, ((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal, SysStringLen(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal), // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL); // address of flag set when default char. used
LPSTR pszVal = (LPSTR) CoTaskMemAlloc(cLen+1); if (NULL == pszVal) hr = E_OUTOFMEMORY; else { cLen = WideCharToMultiByte( CP_ACP, 0, ((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal, SysStringLen(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal), // number of characters in string
pszVal, // address of buffer for new string
cLen+1, // size of buffer
NULL, // address of default for unmappable characters
NULL); // address of flag set when default char. used
SysFreeString(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal); pszVal[cLen] = '\0'; ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_LPSTR; ((PROPVARIANT*)(*ppct)->value.pvValue)->pszVal = pszVal; } } break;
case VT_LPWSTR: { LPWSTR pwszVal = CoTaskStrDup(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal); if (NULL == pwszVal) hr = E_OUTOFMEMORY; else { SysFreeString(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal); ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_LPWSTR; ((PROPVARIANT*)(*ppct)->value.pvValue)->pwszVal = pwszVal; } } break;
case VT_CLSID: { GUID* pGuid = (GUID*) CoTaskMemAlloc(sizeof GUID); if (NULL == pGuid) hr = E_OUTOFMEMORY; else { BOOL bRet = ParseGuid(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal, *pGuid); if ( bRet && GUID_NULL != *pGuid ) { SysFreeString(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal); ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_CLSID; ((PROPVARIANT*)(*ppct)->value.pvValue)->puuid = pGuid; } else { CoTaskMemFree(pGuid); hr = DB_E_CANTCONVERTVALUE; } } } break;
case VT_FILETIME: case VT_DATE: { SYSTEMTIME stValue = {0, 0, 0, 0, 0, 0, 0, 0}; // convert a string to a filetime value
int cItems = swscanf(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal, L"%4hd/%2hd/%2hd %2hd:%2hd:%2hd:%3hd", &stValue.wYear, &stValue.wMonth, &stValue.wDay, &stValue.wHour, &stValue.wMinute, &stValue.wSecond, &stValue.wMilliseconds);
if (1 == cItems) cItems = swscanf(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal, L"%4hd-%2hd-%2hd %2hd:%2hd:%2hd:%3hd", &stValue.wYear, &stValue.wMonth, &stValue.wDay, &stValue.wHour, &stValue.wMinute, &stValue.wSecond, &stValue.wMilliseconds );
if (cItems != 3 && cItems != 6 && cItems != 7) hr = E_FAIL;
//
// Make a sensible split for Year 2000 using the user's system settings
//
if ( stValue.wYear < 100 ) { DWORD dwYearHigh = 0; if ( 0 == GetCalendarInfo ( m_pIPSession->GetLCID(), CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER, 0, 0, &dwYearHigh ) ) { hr = HRESULT_FROM_WIN32 ( GetLastError() ); }
if ( ( dwYearHigh < 99 ) || ( dwYearHigh > 9999 ) ) dwYearHigh = 2029;
WORD wMaxDecade = (WORD) dwYearHigh % 100; WORD wMaxCentury = (WORD) dwYearHigh - wMaxDecade; if ( stValue.wYear <= wMaxDecade ) stValue.wYear += wMaxCentury; else stValue.wYear += ( wMaxCentury - 100 ); }
SysFreeString(((PROPVARIANT*)(*ppct)->value.pvValue)->bstrVal);
int iResult = 0; if (VT_FILETIME == dbType) iResult = SystemTimeToFileTime(&stValue, &((PROPVARIANT*)(*ppct)->value.pvValue)->filetime); else iResult = SystemTimeToVariantTime(&stValue, &((PROPVARIANT*)(*ppct)->value.pvValue)->date); if (0 == iResult) { // SystemTimeTo* conversion failed. Most likely we were given the date in a bogus format.
(*ppct)->hrError = DB_E_CANTCONVERTVALUE; hr = DB_E_CANTCONVERTVALUE; } else ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = dbType; } break;
default: hr = DB_E_CANTCONVERTVALUE; } break;
case VT_FILETIME: switch ( dbType ) { case VT_DATE: { SYSTEMTIME stValue = {0, 0, 0, 0, 0, 0, 0, 0}; if ( FileTimeToSystemTime(&((PROPVARIANT*)(*ppct)->value.pvValue)->filetime, &stValue) ) { int iResult = SystemTimeToVariantTime(&stValue, &((PROPVARIANT*)(*ppct)->value.pvValue)->date); if (0 == iResult) { // SystemTimeToVariantTime failed. Most likely we were given the date in a bogus format.
(*ppct)->hrError = DB_E_CANTCONVERTVALUE; hr = DB_E_CANTCONVERTVALUE; } else ((PROPVARIANT*)(*ppct)->value.pvValue)->vt = VT_DATE; } else hr = DISP_E_TYPEMISMATCH; } break;
default: hr = DB_E_CANTCONVERTVALUE; } break;
default: hr = DB_E_CANTCONVERTVALUE; break; }
error: if (S_OK != hr) { switch ( hr ) { case DB_E_DATAOVERFLOW: m_pIPTProperties->SetErrorHResult(hr, MONSQL_OUT_OF_RANGE); break;
case E_OUTOFMEMORY: m_pIPTProperties->SetErrorHResult(hr, MONSQL_OUT_OF_MEMORY); break;
default: m_pIPTProperties->SetErrorHResult(hr, MONSQL_CANNOT_CONVERT); }
m_pIPTProperties->SetErrorToken((YY_CHAR*)m_yylex.YYText());
switch ( dbType ) { case DBTYPE_UI1: m_pIPTProperties->SetErrorToken(L"DBTYPE_UI1"); break;
case DBTYPE_I1: m_pIPTProperties->SetErrorToken(L"DBTYPE_I1"); break;
case DBTYPE_UI2: m_pIPTProperties->SetErrorToken(L"DBTYPE_UI2"); break;
case DBTYPE_UI4: m_pIPTProperties->SetErrorToken(L"DBTYPE_UI4"); break;
case DBTYPE_UI8: m_pIPTProperties->SetErrorToken(L"DBTYPE_UI8"); break;
case DBTYPE_I2: m_pIPTProperties->SetErrorToken(L"DBTYPE_I2"); break;
case DBTYPE_I4: m_pIPTProperties->SetErrorToken(L"DBTYPE_I4"); break;
case DBTYPE_I8: m_pIPTProperties->SetErrorToken(L"DBTYPE_I8"); break;
case DBTYPE_R4: m_pIPTProperties->SetErrorToken(L"DBTYPE_R4"); break;
case DBTYPE_R8: m_pIPTProperties->SetErrorToken(L"DBTYPE_R8"); break;
case DBTYPE_CY: m_pIPTProperties->SetErrorToken(L"DBTYPE_CY"); break;
case DBTYPE_DATE: m_pIPTProperties->SetErrorToken(L"DBTYPE_DATE"); break;
case DBTYPE_BSTR: m_pIPTProperties->SetErrorToken(L"DBTYPE_BSTR"); break;
case DBTYPE_BOOL: m_pIPTProperties->SetErrorToken(L"DBTYPE_BOOL"); break;
case DBTYPE_GUID: m_pIPTProperties->SetErrorToken(L"DBTYPE_GUID"); break;
case DBTYPE_STR: m_pIPTProperties->SetErrorToken(L"DBTYPE_STR"); break;
case DBTYPE_STR | DBTYPE_BYREF: m_pIPTProperties->SetErrorToken(L"DBTYPE_STR|DBTYPE_BYREF"); break;
case DBTYPE_WSTR: m_pIPTProperties->SetErrorToken(L"DBTYPE_WSTR"); break;
case DBTYPE_WSTR | DBTYPE_BYREF: m_pIPTProperties->SetErrorToken(L"DBTYPE_WSTR | DBTYPE_BYREF"); break;
case VT_FILETIME: m_pIPTProperties->SetErrorToken(L"VT_FILETIME"); break;
default: m_pIPTProperties->SetErrorToken(L"DBTYPE_NULL"); break; } } return hr; }
//+-------------------------------------------------------------------------
//
// Member: CYYBase::yyprimebuffer, public
//
// Synopsis: Prime lexer with text (passthrough to lexer)
//
// Arguments: [pszBuffer] -- Buffer
//
// History: 30-Nov-1999 KyleP Moved from YYPARSER
//
//--------------------------------------------------------------------------
void CYYBase::yyprimebuffer(YY_CHAR *pszBuffer) { m_yylex.yyprimebuffer(pszBuffer); }
//+-------------------------------------------------------------------------
//
// Member: CYYBase::yyprimelexer, public
//
// Synopsis: Prime lexer with initial token (passthrough to lexer)
//
// Arguments: [eToken] -- Token
//
// History: 30-Nov-1999 KyleP Moved from YYPARSER
//
//--------------------------------------------------------------------------
void CYYBase::yyprimelexer(int eToken) { m_yylex.yyprimelexer(eToken); }
//+-------------------------------------------------------------------------
//
// Member: CYYBase::yyerror, protected
//
// Synopsis: Report parsing errors
//
// Arguments: [szError] -- Error string
//
// History: 30-Nov-1999 KyleP Moved from YYPARSER
//
//--------------------------------------------------------------------------
void CYYBase::yyerror( char const * szError ) { }
|