//--------------------------------------------------------------------------- // NtlParse.cpp - parses a ".ntl" file (Native Theme Language) //--------------------------------------------------------------------------- #include "stdafx.h" #include "scanner.h" #include "NtlParse.h" #include "Utils.h" #include "SysMetrics.h" #include "stringtable.h" //--------------------------------------------------------------------------- #define SYSCOLOR_STRINGS #include "SysColors.h" //--------------------------------------------------------------------------- CNtlParser::CNtlParser() { _pPCode = NULL; _iPCodeAllocSize = 0; _iIfLevel = 0; for (int i=0; i < ARRAYSIZE(_iStateOffsets); i++) _iStateOffsets[i] = 0; } //--------------------------------------------------------------------------- HRESULT CNtlParser::SourceError(int iMsgResId, ...) { va_list args; va_start(args, iMsgResId); LPCWSTR pszParam1 = va_arg(args, LPCWSTR); LPCWSTR pszParam2 = va_arg(args, LPCWSTR); HRESULT hr = MakeErrorEx(iMsgResId, pszParam1, pszParam2, _scan._szFileName, _scan._szLineBuff, _scan._iLineNum); va_end(args); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseBuffer(LPCWSTR pszSource, LPCWSTR pszSourceFileName, INtlParserCallBack *pCallBack, OUT BYTE **ppPCode, OUT int *piLen) { HRESULT hr = S_OK; _pCallBack = pCallBack; _scan.AttachMultiLineBuffer(pszSource, pszSourceFileName); //---- jump to state table at end ---- hr = EmitByte(NTL_JMP); if (FAILED(hr)) goto exit; int iStateJumpOffset; iStateJumpOffset = int(_u.pb - _pPCode); hr = EmitInt(0); if (FAILED(hr)) goto exit; if (! _scan.GetChar('[')) { if (! _scan.EndOfFile()) { hr = SourceError(IDS_MISSING_SECTION_LBRACKET); goto exit; } } while (! _scan.EndOfFile()) // process each section { WCHAR section[_MAX_PATH+1]; _scan.GetId(section); if (lstrcmpi(section, L"OptionBits")==0) { hr = ParseOptionBitsSection(); } else if (lstrcmpi(section, L"Drawing")==0) { hr = ParseDrawingSection(); } else // "globals", "sysmetrics", or class section { hr = SourceError(IDS_UNKNOWN_SECTION_NAME); } if (FAILED(hr)) break; } if (FAILED(hr)) goto exit; //---- update first jump to state table ---- int *ip; ip = (int *)(_pPCode + iStateJumpOffset); *ip = (int)(_u.pb - _pPCode); //---- build state table at end of stream ---- BYTE iMaxState; iMaxState = 0; for (BYTE i=ARRAYSIZE(_iStateOffsets)-1; i >= 0; i--) { if (_iStateOffsets[i]) { iMaxState = i; break; } } hr = EmitByte(iMaxState); if (FAILED(hr)) goto exit; for (int i=1; i <= iMaxState; i++) { hr = EmitInt(_iStateOffsets[i]); if (FAILED(hr)) goto exit; } exit: if (SUCCEEDED(hr)) { *ppPCode = _pPCode; *piLen = (int)(_u.pb - _pPCode); } else delete [] _pPCode; _pPCode = NULL; _iPCodeAllocSize = 0; return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseOptionBitsSection() { HRESULT hr = S_OK; WCHAR szOptionName[_MAX_PATH+1]; if (!_scan.GetChar(']')) hr = SourceError(IDS_EXPECTED_END_OF_SECTION); else { while (! _scan.EndOfFile()) { if (_scan.GetChar('[')) // start of new section break; if (! _scan.GetId(szOptionName)) { hr = SourceError(IDS_OPTIONNAME_EXPECTED); break; } if (! _scan.GetChar('=')) { hr = SourceError(IDS_EXPECTED_EQUALS_SIGN); break; } int iOptionValue; if (! _scan.GetNumber(&iOptionValue)) { hr = SourceError(IDS_INT_EXPECTED); break; } hr = AddOptionBitName(szOptionName, iOptionValue); if (FAILED(hr)) break; } } if (FAILED(hr)) goto exit; exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::AddOptionBitName(LPCWSTR szOptionName, int iOptionValue) { HRESULT hr = S_OK; OPTIONBITENTRY option; option.csName = szOptionName; option.iValue = iOptionValue; for (int i=0; i < _OptionBits.m_nSize; i++) { if ((iOptionValue == _OptionBits[i].iValue) && (lstrcmpi(szOptionName, _OptionBits[i].csName)==0)) break; } if (i < _OptionBits.m_nSize) // found hr = SourceError(IDS_ALREADY_DEFINED); else _OptionBits.Add(option); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::GetBitnumVal(LPCWSTR szName, BYTE *piValue) { HRESULT hr; hr = MakeErrorEx(IDS_UNKNOWN_BITNAME, szName); for (BYTE i=0; i < _OptionBits.m_nSize; i++) { if (lstrcmpi(szName, _OptionBits[i].csName)==0) { *piValue = i; hr = S_OK; break; } } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseDrawingSection() { HRESULT hr = S_OK; WCHAR szStateName[_MAX_PATH+1]; WCHAR szCmd[_MAX_PATH+1]; if (! _scan.GetChar('(')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } if (! _scan.GetId(szStateName)) { hr = SourceError(IDS_STATENAME_EXPECTED); goto exit; } BYTE iStateNum; hr = GetStateNum(szStateName, &iStateNum); if (FAILED(hr)) goto exit; if ((iStateNum < 1) || (iStateNum > MAX_STATES)) { hr = SourceError(IDS_UNKNOWN_STATE, szStateName); goto exit; } _iStateOffsets[iStateNum] = int(_u.pb - _pPCode); if (! _scan.GetChar(']')) { hr = SourceError(IDS_RBRACKET_EXPECTED); goto exit; } while (! _scan.EndOfFile()) { if (_scan.GetChar('[')) // start of new section break; if (! _scan.GetId(szCmd)) { hr = SourceError(IDS_DRAWINGPROP_EXPECTED); break; } if (! _scan.GetChar('=')) { hr = SourceError(IDS_EXPECTED_EQUALS_SIGN); break; } if (lstrcmpi(szCmd, L"AddBorder")==0) hr = ParseAddBorder(); else if (lstrcmpi(szCmd, L"FillBorder")==0) hr = ParseFillBorder(); else if (lstrcmpi(szCmd, L"LogicalRect")==0) hr = ParseLogicalRect(); else if (lstrcmpi(szCmd, L"FillBrush")==0) hr = ParseFillBrush(); else if (lstrcmpi(szCmd, L"LineBrush")==0) hr = ParseLineBrush(); else if (lstrcmpi(szCmd, L"MoveTo")==0) hr = ParseMoveTo(); else if (lstrcmpi(szCmd, L"LineTo")==0) hr = ParseLineTo(); else if (lstrcmpi(szCmd, L"CurveTo")==0) hr = ParseCurveTo(); else if (lstrcmpi(szCmd, L"Shape")==0) hr = ParseShape(); else if (lstrcmpi(szCmd, L"EndShape")==0) hr = ParseEndShape(); else if (lstrcmpi(szCmd, L"if")==0) hr = ParseIf(); else if (lstrcmpi(szCmd, L"else")==0) hr = ParseElse(); else if (lstrcmpi(szCmd, L"endif")==0) hr = ParseEndIf(); else if (lstrcmpi(szCmd, L"SetOption")==0) hr = ParseSetOption(); else if (lstrcmpi(szCmd, L"GotoState")==0) hr = ParseGotoState(); else hr = SourceError(IDS_DRAWINGPROP_EXPECTED); if (FAILED(hr)) goto exit; if (! _scan.EndOfLine()) { hr = SourceError(IDS_EXTRA_PROP_TEXT, _scan._p); goto exit; } _scan.ForceNextLine(); } if (SUCCEEDED(hr)) hr = EmitByte(NTL_RETURN); // return to caller (no params) exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseLogicalRect() { HRESULT hr; hr = EmitByte(NTL_LOGRECT); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"RECT")) { hr = SourceError(IDS_RECT_EXPECTED); } else { hr = ParseEmitRect(); } } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::EmitCheck(int iLen) { HRESULT hr = S_OK; int iOffset = (int)(_u.pb - _pPCode); if (iOffset + iLen > _iPCodeAllocSize) { int iSize = _iPCodeAllocSize + 4096; BYTE *pNew = (BYTE *)realloc(_pPCode, iSize); if (! pNew) { hr = MakeError32(E_OUTOFMEMORY); } else { _pPCode = pNew; _iPCodeAllocSize = iSize; _u.pb = _pPCode + iOffset; } } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::EmitByte(BYTE eOpCode) { HRESULT hr = EmitCheck(1); if (SUCCEEDED(hr)) { *_u.pb++ = eOpCode; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::EmitInt(int iValue) { HRESULT hr = EmitCheck(sizeof(int)); if (SUCCEEDED(hr)) { *_u.pi++ = iValue; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::EmitShort(SHORT sValue) { HRESULT hr = EmitCheck(sizeof(SHORT)); if (SUCCEEDED(hr)) { *_u.ps++ = sValue; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::EmitString(LPCWSTR szValue) { int len = sizeof(WCHAR) * (1 + lstrlen(szValue)); HRESULT hr = EmitCheck(len); if (SUCCEEDED(hr)) { lstrcpy(_u.pw, szValue); _u.pb += len; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitPoint() { HRESULT hr = S_OK; int ix, iy; if (! _scan.GetNumber(&ix)) { hr = SourceError(IDS_INT_EXPECTED); goto exit; } if (! _scan.GetNumber(&iy)) { hr = SourceError(IDS_INT_EXPECTED); goto exit; } hr = EmitInt(ix); if (FAILED(hr)) goto exit; hr = EmitInt(iy); if (FAILED(hr)) goto exit; exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitRect() { HRESULT hr = S_OK; int iValue; for (int i=0; i < 4; i++) { if (! _scan.GetNumber(&iValue)) { hr = SourceError(IDS_INT_EXPECTED); goto exit; } hr = EmitInt(iValue); if (FAILED(hr)) goto exit; } exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitSize2() { HRESULT hr = ParseEmitSize(); // first size if (FAILED(hr)) goto exit; if (_scan.GetChar(',')) { hr = ParseEmitSize(); // second size if (FAILED(hr)) goto exit; } exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitSize4() { HRESULT hr = ParseEmitSize(); // first size if (FAILED(hr)) goto exit; if (_scan.GetChar(',')) { hr = ParseEmitSize(); // second size if (FAILED(hr)) goto exit; if (_scan.GetChar(',')) { hr = ParseEmitSize(); // third size if (FAILED(hr)) goto exit; if (! _scan.GetChar(',')) { hr = SourceError(IDS_COMMA_EXPECTED); goto exit; } hr = ParseEmitSize(); // forth size if (FAILED(hr)) goto exit; } } exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitSize() { HRESULT hr = S_OK; int iValue; WCHAR szId[_MAX_PATH+1]; if (_scan.GetNumber(&iValue)) { hr = EmitInt(iValue); if (FAILED(hr)) goto exit; } else if (_scan.GetId(szId)) { int cnt = ARRAYSIZE(pszSysMetricIntNames); for (SHORT i=0; i < cnt; i++) { if (lstrcmpi(szId, pszSysMetricIntNames[i])==0) { hr = EmitByte(PT_SYSMETRICINDEX); if (FAILED(hr)) goto exit; hr = EmitShort(i); if (FAILED(hr)) goto exit; break; } if (i == cnt) { hr = SourceError(IDS_SIZE_EXPECTED); goto exit; } } } else hr = SourceError(IDS_SIZE_EXPECTED); exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitImagefile() { HRESULT hr = S_OK; int iIndex; if (! _scan.GetNumber(&iIndex)) iIndex = 0; //---- emit imagefile ---- hr = EmitByte(PT_IMAGEFILE); if (FAILED(hr)) goto exit; hr = EmitByte((BYTE)iIndex); if (FAILED(hr)) goto exit; exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitColor4() { HRESULT hr = ParseEmitColor(); // first color if (FAILED(hr)) goto exit; if (_scan.GetChar(',')) { hr = ParseEmitColor(); // second color if (FAILED(hr)) goto exit; if (_scan.GetChar(',')) { hr = ParseEmitColor(); // third color if (FAILED(hr)) goto exit; if (! _scan.GetChar(',')) { hr = SourceError(IDS_COMMA_EXPECTED); goto exit; } hr = ParseEmitColor(); // forth color if (FAILED(hr)) goto exit; } } exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitColor() { HRESULT hr = S_OK; int iRed, iGreen, iBlue; WCHAR szColorId[_MAX_PATH+1]; if (_scan.GetNumber(&iRed)) // RGB numbers specified { hr = EmitByte(PT_COLORREF); if (FAILED(hr)) goto exit; if (! _scan.GetNumber(&iGreen)) { hr = SourceError(IDS_INT_EXPECTED); goto exit; } if (! _scan.GetNumber(&iBlue)) { hr = SourceError(IDS_INT_EXPECTED); goto exit; } COLORREF cr = RGB(iRed, iGreen, iBlue); hr = EmitInt(cr); if (FAILED(hr)) goto exit; } else if (_scan.GetId(szColorId)) { if (lstrcmpi(szColorId, L"NONE")) hr = EmitByte(PT_COLORNULL); else { for (SHORT i=0; i < iSysColorSize; i++) { if (lstrcmpi(szColorId, pszSysColorNames[i])==0) { hr = EmitByte(PT_SYSCOLORINDEX); if (SUCCEEDED(hr)) hr = EmitShort(i); break; } } if (i == iSysColorSize) hr = SourceError(IDS_COLORVALUE_EXPECTED); } } else hr = SourceError(IDS_COLORVALUE_EXPECTED); exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEmitNone() { HRESULT hr = EmitByte(PT_COLORNULL); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseAddBorder() { HRESULT hr = S_OK; while (SUCCEEDED(hr)) { if (_scan.GetKeyword(L"SIZE")) { hr = ParseEmitSize4(); } else if (_scan.GetKeyword(L"COLOR")) { hr = ParseEmitColor4(); } else break; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseFillBorder() { HRESULT hr = S_OK; while (SUCCEEDED(hr)) { if (_scan.GetKeyword(L"COLOR")) { hr = ParseEmitColor(); } else if (_scan.GetKeyword(L"IMAGEFILE")) { hr = ParseEmitImagefile(); } else if (_scan.GetKeyword(L"NONE")) { hr = ParseEmitNone(); } else break; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseFillBrush() { HRESULT hr; hr = EmitByte(NTL_FILLBRUSH); while (SUCCEEDED(hr)) { if (_scan.GetKeyword(L"COLOR")) { hr = ParseEmitColor(); } else if (_scan.GetKeyword(L"IMAGEFILE")) { hr = ParseEmitImagefile(); } else if (_scan.GetKeyword(L"NONE")) { hr = ParseEmitNone(); } else break; } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseLineBrush() { HRESULT hr; hr = EmitByte(NTL_LINEBRUSH); if (_scan.GetKeyword(L"NONE")) { hr = ParseEmitNone(); } else { while (SUCCEEDED(hr)) { if (_scan.GetKeyword(L"COLOR")) { hr = ParseEmitColor(); } else if (_scan.GetKeyword(L"SIZE")) { hr = ParseEmitSize(); } else break; } } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseMoveTo() { HRESULT hr; hr = EmitByte(NTL_MOVETO); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"POINT")) hr = SourceError(IDS_POINT_EXPECTED); else hr = ParseEmitPoint(); } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseLineTo() { HRESULT hr; hr = EmitByte(NTL_LINETO); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"POINT")) hr = SourceError(IDS_POINT_EXPECTED); else hr = ParseEmitPoint(); } return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseCurveTo() { HRESULT hr; hr = EmitByte(NTL_CURVETO); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"POINT")) hr = SourceError(IDS_POINT_EXPECTED); } if (SUCCEEDED(hr)) hr = ParseEmitPoint(); if (SUCCEEDED(hr)) hr = ParseEmitPoint(); if (SUCCEEDED(hr)) hr = ParseEmitPoint(); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseShape() { HRESULT hr; hr = EmitByte(NTL_SHAPE); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"POINT")) hr = SourceError(IDS_POINT_EXPECTED); } if (SUCCEEDED(hr)) hr = ParseEmitPoint(); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEndShape() { HRESULT hr; hr = EmitByte(NTL_ENDSHAPE); if (SUCCEEDED(hr)) { if (! _scan.GetKeyword(L"POINT")) hr = SourceError(IDS_POINT_EXPECTED); } if (SUCCEEDED(hr)) hr = ParseEmitPoint(); return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseIf() { HRESULT hr = S_OK; WCHAR szId[_MAX_PATH+1]; NTL_OPCODE opcode; IFRECORD ifrec; if (! _scan.GetId(szId)) { hr = SourceError(IDS_OPTIONNAME_EXPECTED); goto exit; } BYTE iBitnum; hr = GetBitnumVal(szId, &iBitnum); if (FAILED(hr)) goto exit; if (! _scan.GetChar('(')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } if (_scan.GetKeyword(L"on")) { opcode = NTL_JMPOFF; } else if (_scan.GetKeyword(L"off")) { opcode = NTL_JMPON; } else { hr = SourceError(IDS_ONOFF_EXPECTED); goto exit; } if (! _scan.GetChar(')')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } hr = EmitByte(static_cast(opcode)); if (FAILED(hr)) goto exit; hr = EmitByte(iBitnum); if (FAILED(hr)) goto exit; //---- create a new active IFRECORD ---- if (_iIfLevel == MAX_IF_NESTING) { hr = SourceError(IDS_MAX_IFNESTING); goto exit; } ifrec.iBitNum = iBitnum; ifrec.fIfOn = (opcode == NTL_JMPOFF); ifrec.iIfOffset = (int)(_u.pb - _pPCode); ifrec.iElseOffset = 0; _IfStack[_iIfLevel++] = ifrec; //---- emit the jump offset ---- hr = EmitInt(0); // will be fixed up later if (FAILED(hr)) goto exit; exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseElse() { HRESULT hr = S_OK; WCHAR szId[_MAX_PATH+1]; if (! _scan.GetId(szId)) { hr = SourceError(IDS_OPTIONNAME_EXPECTED); goto exit; } BYTE iBitnum; hr = GetBitnumVal(szId, &iBitnum); if (FAILED(hr)) goto exit; if (! _scan.GetChar('(')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } BOOL fElseOn; if (_scan.GetKeyword(L"on")) { fElseOn = TRUE; } else if (_scan.GetKeyword(L"off")) { fElseOn = FALSE; } else { hr = SourceError(IDS_ONOFF_EXPECTED); goto exit; } if (! _scan.GetChar(')')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } //---- emit the JMP ---- hr = EmitByte(NTL_JMP); if (FAILED(hr)) goto exit; //---- validate the IFRECORD ---- if (! _iIfLevel) { hr = SourceError(IDS_NOMATCHINGIF); goto exit; } IFRECORD *ifrec; ifrec = &_IfStack[_iIfLevel - 1]; if (ifrec->iBitNum != iBitnum) { hr = SourceError(IDS_WRONG_IF_BITNAME); goto exit; } if (ifrec->fIfOn == fElseOn) { hr = SourceError(IDS_WRONG_ELSE_PARAM); goto exit; } //---- update the IFRECORD ---- ifrec->iElseOffset = (int)(_u.pb - _pPCode); //---- emit the jump offset ---- hr = EmitInt(0); // will be fixed up later //---- fixup the IF jmp ---- int *ip; ip = (int *)(_pPCode + ifrec->iIfOffset); *ip = (int)(_u.pb - _pPCode); // point to next instruction ifrec->iIfOffset = 0; // update no longer needed exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseEndIf() { HRESULT hr = S_OK; WCHAR szId[_MAX_PATH+1]; if (! _scan.GetId(szId)) { hr = SourceError(IDS_OPTIONNAME_EXPECTED); goto exit; } BYTE iBitnum; hr = GetBitnumVal(szId, &iBitnum); if (FAILED(hr)) goto exit; //---- validate the IFRECORD ---- if (! _iIfLevel) { hr = SourceError(IDS_NOMATCHINGIF); goto exit; } IFRECORD *ifrec; ifrec = &_IfStack[_iIfLevel - 1]; if (ifrec->iBitNum != iBitnum) { hr = SourceError(IDS_WRONG_IF_BITNAME); goto exit; } //---- fixup where needed ---- int *ip; if (ifrec->iIfOffset) ip = (int *)(_pPCode + ifrec->iIfOffset); else ip = (int *)(_pPCode + ifrec->iElseOffset); *ip = (int)(_u.pb - _pPCode); // point to next instruction _iIfLevel--; exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseSetOption() { HRESULT hr = S_OK; WCHAR szId[_MAX_PATH+1]; if (! _scan.GetId(szId)) { hr = SourceError(IDS_OPTIONNAME_EXPECTED); goto exit; } BYTE iBitnum; hr = GetBitnumVal(szId, &iBitnum); if (FAILED(hr)) goto exit; if (! _scan.GetChar('(')) { hr = SourceError(IDS_LEFTPAREN_EXPECTED); goto exit; } BYTE opcode; if (_scan.GetKeyword(L"on")) { opcode = NTL_SETOPTION; } else if (_scan.GetKeyword(L"off")) { opcode = NTL_CLROPTION; } else { hr = SourceError(IDS_ONOFF_EXPECTED); goto exit; } hr = EmitByte(opcode); if (FAILED(hr)) goto exit; hr = EmitByte(iBitnum); exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::ParseGotoState() { HRESULT hr = S_OK; WCHAR szId[_MAX_PATH+1]; if (! _scan.GetId(szId)) { hr = SourceError(IDS_STATEID_EXPECTED); goto exit; } BYTE iStateNum; hr = GetStateNum(szId, &iStateNum); if (FAILED(hr)) goto exit; if ((iStateNum < 1) || (iStateNum > MAX_STATES)) { hr = SourceError(IDS_BAD_STATENUM); goto exit; } if (! _iStateOffsets[iStateNum]) { hr = SourceError(IDS_STATE_MUST_BE_DEFINED, szId); goto exit; } EmitByte(NTL_JMP); EmitInt(_iStateOffsets[iStateNum]); exit: return hr; } //--------------------------------------------------------------------------- HRESULT CNtlParser::GetStateNum(LPCWSTR pszStateName, BYTE *piNum) { HRESULT hr; if (_pCallBack) hr = _pCallBack->GetStateNum(pszStateName, piNum); else { hr = MakeError32(ERROR_INTERNAL_ERROR); Log(LOG_ERROR, L"CNtlParser::GetStateNum - no callback defined"); } return hr; } //---------------------------------------------------------------------------