Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1191 lines
26 KiB

  1. //---------------------------------------------------------------------------
  2. // NtlParse.cpp - parses a ".ntl" file (Native Theme Language)
  3. //---------------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "scanner.h"
  6. #include "NtlParse.h"
  7. #include "Utils.h"
  8. #include "SysMetrics.h"
  9. #include "stringtable.h"
  10. //---------------------------------------------------------------------------
  11. #define SYSCOLOR_STRINGS
  12. #include "SysColors.h"
  13. //---------------------------------------------------------------------------
  14. CNtlParser::CNtlParser()
  15. {
  16. _pPCode = NULL;
  17. _iPCodeAllocSize = 0;
  18. _iIfLevel = 0;
  19. for (int i=0; i < ARRAYSIZE(_iStateOffsets); i++)
  20. _iStateOffsets[i] = 0;
  21. }
  22. //---------------------------------------------------------------------------
  23. HRESULT CNtlParser::SourceError(int iMsgResId, ...)
  24. {
  25. va_list args;
  26. va_start(args, iMsgResId);
  27. LPCWSTR pszParam1 = va_arg(args, LPCWSTR);
  28. LPCWSTR pszParam2 = va_arg(args, LPCWSTR);
  29. HRESULT hr = MakeErrorEx(iMsgResId, pszParam1, pszParam2, _scan._szFileName,
  30. _scan._szLineBuff, _scan._iLineNum);
  31. va_end(args);
  32. return hr;
  33. }
  34. //---------------------------------------------------------------------------
  35. HRESULT CNtlParser::ParseBuffer(LPCWSTR pszSource, LPCWSTR pszSourceFileName,
  36. INtlParserCallBack *pCallBack, OUT BYTE **ppPCode, OUT int *piLen)
  37. {
  38. HRESULT hr = S_OK;
  39. _pCallBack = pCallBack;
  40. _scan.AttachMultiLineBuffer(pszSource, pszSourceFileName);
  41. //---- jump to state table at end ----
  42. hr = EmitByte(NTL_JMP);
  43. if (FAILED(hr))
  44. goto exit;
  45. int iStateJumpOffset;
  46. iStateJumpOffset = int(_u.pb - _pPCode);
  47. hr = EmitInt(0);
  48. if (FAILED(hr))
  49. goto exit;
  50. if (! _scan.GetChar('['))
  51. {
  52. if (! _scan.EndOfFile())
  53. {
  54. hr = SourceError(IDS_MISSING_SECTION_LBRACKET);
  55. goto exit;
  56. }
  57. }
  58. while (! _scan.EndOfFile()) // process each section
  59. {
  60. WCHAR section[_MAX_PATH+1];
  61. _scan.GetId(section);
  62. if (lstrcmpi(section, L"OptionBits")==0)
  63. {
  64. hr = ParseOptionBitsSection();
  65. }
  66. else if (lstrcmpi(section, L"Drawing")==0)
  67. {
  68. hr = ParseDrawingSection();
  69. }
  70. else // "globals", "sysmetrics", or class section
  71. {
  72. hr = SourceError(IDS_UNKNOWN_SECTION_NAME);
  73. }
  74. if (FAILED(hr))
  75. break;
  76. }
  77. if (FAILED(hr))
  78. goto exit;
  79. //---- update first jump to state table ----
  80. int *ip;
  81. ip = (int *)(_pPCode + iStateJumpOffset);
  82. *ip = (int)(_u.pb - _pPCode);
  83. //---- build state table at end of stream ----
  84. BYTE iMaxState;
  85. iMaxState = 0;
  86. for (BYTE i=ARRAYSIZE(_iStateOffsets)-1; i >= 0; i--)
  87. {
  88. if (_iStateOffsets[i])
  89. {
  90. iMaxState = i;
  91. break;
  92. }
  93. }
  94. hr = EmitByte(iMaxState);
  95. if (FAILED(hr))
  96. goto exit;
  97. for (int i=1; i <= iMaxState; i++)
  98. {
  99. hr = EmitInt(_iStateOffsets[i]);
  100. if (FAILED(hr))
  101. goto exit;
  102. }
  103. exit:
  104. if (SUCCEEDED(hr))
  105. {
  106. *ppPCode = _pPCode;
  107. *piLen = (int)(_u.pb - _pPCode);
  108. }
  109. else
  110. delete [] _pPCode;
  111. _pPCode = NULL;
  112. _iPCodeAllocSize = 0;
  113. return hr;
  114. }
  115. //---------------------------------------------------------------------------
  116. HRESULT CNtlParser::ParseOptionBitsSection()
  117. {
  118. HRESULT hr = S_OK;
  119. WCHAR szOptionName[_MAX_PATH+1];
  120. if (!_scan.GetChar(']'))
  121. hr = SourceError(IDS_EXPECTED_END_OF_SECTION);
  122. else
  123. {
  124. while (! _scan.EndOfFile())
  125. {
  126. if (_scan.GetChar('[')) // start of new section
  127. break;
  128. if (! _scan.GetId(szOptionName))
  129. {
  130. hr = SourceError(IDS_OPTIONNAME_EXPECTED);
  131. break;
  132. }
  133. if (! _scan.GetChar('='))
  134. {
  135. hr = SourceError(IDS_EXPECTED_EQUALS_SIGN);
  136. break;
  137. }
  138. int iOptionValue;
  139. if (! _scan.GetNumber(&iOptionValue))
  140. {
  141. hr = SourceError(IDS_INT_EXPECTED);
  142. break;
  143. }
  144. hr = AddOptionBitName(szOptionName, iOptionValue);
  145. if (FAILED(hr))
  146. break;
  147. }
  148. }
  149. if (FAILED(hr))
  150. goto exit;
  151. exit:
  152. return hr;
  153. }
  154. //---------------------------------------------------------------------------
  155. HRESULT CNtlParser::AddOptionBitName(LPCWSTR szOptionName, int iOptionValue)
  156. {
  157. HRESULT hr = S_OK;
  158. OPTIONBITENTRY option;
  159. option.csName = szOptionName;
  160. option.iValue = iOptionValue;
  161. for (int i=0; i < _OptionBits.m_nSize; i++)
  162. {
  163. if ((iOptionValue == _OptionBits[i].iValue) && (lstrcmpi(szOptionName, _OptionBits[i].csName)==0))
  164. break;
  165. }
  166. if (i < _OptionBits.m_nSize) // found
  167. hr = SourceError(IDS_ALREADY_DEFINED);
  168. else
  169. _OptionBits.Add(option);
  170. return hr;
  171. }
  172. //---------------------------------------------------------------------------
  173. HRESULT CNtlParser::GetBitnumVal(LPCWSTR szName, BYTE *piValue)
  174. {
  175. HRESULT hr;
  176. hr = MakeErrorEx(IDS_UNKNOWN_BITNAME, szName);
  177. for (BYTE i=0; i < _OptionBits.m_nSize; i++)
  178. {
  179. if (lstrcmpi(szName, _OptionBits[i].csName)==0)
  180. {
  181. *piValue = i;
  182. hr = S_OK;
  183. break;
  184. }
  185. }
  186. return hr;
  187. }
  188. //---------------------------------------------------------------------------
  189. HRESULT CNtlParser::ParseDrawingSection()
  190. {
  191. HRESULT hr = S_OK;
  192. WCHAR szStateName[_MAX_PATH+1];
  193. WCHAR szCmd[_MAX_PATH+1];
  194. if (! _scan.GetChar('('))
  195. {
  196. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  197. goto exit;
  198. }
  199. if (! _scan.GetId(szStateName))
  200. {
  201. hr = SourceError(IDS_STATENAME_EXPECTED);
  202. goto exit;
  203. }
  204. BYTE iStateNum;
  205. hr = GetStateNum(szStateName, &iStateNum);
  206. if (FAILED(hr))
  207. goto exit;
  208. if ((iStateNum < 1) || (iStateNum > MAX_STATES))
  209. {
  210. hr = SourceError(IDS_UNKNOWN_STATE, szStateName);
  211. goto exit;
  212. }
  213. _iStateOffsets[iStateNum] = int(_u.pb - _pPCode);
  214. if (! _scan.GetChar(']'))
  215. {
  216. hr = SourceError(IDS_RBRACKET_EXPECTED);
  217. goto exit;
  218. }
  219. while (! _scan.EndOfFile())
  220. {
  221. if (_scan.GetChar('[')) // start of new section
  222. break;
  223. if (! _scan.GetId(szCmd))
  224. {
  225. hr = SourceError(IDS_DRAWINGPROP_EXPECTED);
  226. break;
  227. }
  228. if (! _scan.GetChar('='))
  229. {
  230. hr = SourceError(IDS_EXPECTED_EQUALS_SIGN);
  231. break;
  232. }
  233. if (lstrcmpi(szCmd, L"AddBorder")==0)
  234. hr = ParseAddBorder();
  235. else if (lstrcmpi(szCmd, L"FillBorder")==0)
  236. hr = ParseFillBorder();
  237. else if (lstrcmpi(szCmd, L"LogicalRect")==0)
  238. hr = ParseLogicalRect();
  239. else if (lstrcmpi(szCmd, L"FillBrush")==0)
  240. hr = ParseFillBrush();
  241. else if (lstrcmpi(szCmd, L"LineBrush")==0)
  242. hr = ParseLineBrush();
  243. else if (lstrcmpi(szCmd, L"MoveTo")==0)
  244. hr = ParseMoveTo();
  245. else if (lstrcmpi(szCmd, L"LineTo")==0)
  246. hr = ParseLineTo();
  247. else if (lstrcmpi(szCmd, L"CurveTo")==0)
  248. hr = ParseCurveTo();
  249. else if (lstrcmpi(szCmd, L"Shape")==0)
  250. hr = ParseShape();
  251. else if (lstrcmpi(szCmd, L"EndShape")==0)
  252. hr = ParseEndShape();
  253. else if (lstrcmpi(szCmd, L"if")==0)
  254. hr = ParseIf();
  255. else if (lstrcmpi(szCmd, L"else")==0)
  256. hr = ParseElse();
  257. else if (lstrcmpi(szCmd, L"endif")==0)
  258. hr = ParseEndIf();
  259. else if (lstrcmpi(szCmd, L"SetOption")==0)
  260. hr = ParseSetOption();
  261. else if (lstrcmpi(szCmd, L"GotoState")==0)
  262. hr = ParseGotoState();
  263. else
  264. hr = SourceError(IDS_DRAWINGPROP_EXPECTED);
  265. if (FAILED(hr))
  266. goto exit;
  267. if (! _scan.EndOfLine())
  268. {
  269. hr = SourceError(IDS_EXTRA_PROP_TEXT, _scan._p);
  270. goto exit;
  271. }
  272. _scan.ForceNextLine();
  273. }
  274. if (SUCCEEDED(hr))
  275. hr = EmitByte(NTL_RETURN); // return to caller (no params)
  276. exit:
  277. return hr;
  278. }
  279. //---------------------------------------------------------------------------
  280. HRESULT CNtlParser::ParseLogicalRect()
  281. {
  282. HRESULT hr;
  283. hr = EmitByte(NTL_LOGRECT);
  284. if (SUCCEEDED(hr))
  285. {
  286. if (! _scan.GetKeyword(L"RECT"))
  287. {
  288. hr = SourceError(IDS_RECT_EXPECTED);
  289. }
  290. else
  291. {
  292. hr = ParseEmitRect();
  293. }
  294. }
  295. return hr;
  296. }
  297. //---------------------------------------------------------------------------
  298. HRESULT CNtlParser::EmitCheck(int iLen)
  299. {
  300. HRESULT hr = S_OK;
  301. int iOffset = (int)(_u.pb - _pPCode);
  302. if (iOffset + iLen > _iPCodeAllocSize)
  303. {
  304. int iSize = _iPCodeAllocSize + 4096;
  305. BYTE *pNew = (BYTE *)realloc(_pPCode, iSize);
  306. if (! pNew)
  307. {
  308. hr = MakeError32(E_OUTOFMEMORY);
  309. }
  310. else
  311. {
  312. _pPCode = pNew;
  313. _iPCodeAllocSize = iSize;
  314. _u.pb = _pPCode + iOffset;
  315. }
  316. }
  317. return hr;
  318. }
  319. //---------------------------------------------------------------------------
  320. HRESULT CNtlParser::EmitByte(BYTE eOpCode)
  321. {
  322. HRESULT hr = EmitCheck(1);
  323. if (SUCCEEDED(hr))
  324. {
  325. *_u.pb++ = eOpCode;
  326. }
  327. return hr;
  328. }
  329. //---------------------------------------------------------------------------
  330. HRESULT CNtlParser::EmitInt(int iValue)
  331. {
  332. HRESULT hr = EmitCheck(sizeof(int));
  333. if (SUCCEEDED(hr))
  334. {
  335. *_u.pi++ = iValue;
  336. }
  337. return hr;
  338. }
  339. //---------------------------------------------------------------------------
  340. HRESULT CNtlParser::EmitShort(SHORT sValue)
  341. {
  342. HRESULT hr = EmitCheck(sizeof(SHORT));
  343. if (SUCCEEDED(hr))
  344. {
  345. *_u.ps++ = sValue;
  346. }
  347. return hr;
  348. }
  349. //---------------------------------------------------------------------------
  350. HRESULT CNtlParser::EmitString(LPCWSTR szValue)
  351. {
  352. int len = sizeof(WCHAR) * (1 + lstrlen(szValue));
  353. HRESULT hr = EmitCheck(len);
  354. if (SUCCEEDED(hr))
  355. {
  356. lstrcpy(_u.pw, szValue);
  357. _u.pb += len;
  358. }
  359. return hr;
  360. }
  361. //---------------------------------------------------------------------------
  362. HRESULT CNtlParser::ParseEmitPoint()
  363. {
  364. HRESULT hr = S_OK;
  365. int ix, iy;
  366. if (! _scan.GetNumber(&ix))
  367. {
  368. hr = SourceError(IDS_INT_EXPECTED);
  369. goto exit;
  370. }
  371. if (! _scan.GetNumber(&iy))
  372. {
  373. hr = SourceError(IDS_INT_EXPECTED);
  374. goto exit;
  375. }
  376. hr = EmitInt(ix);
  377. if (FAILED(hr))
  378. goto exit;
  379. hr = EmitInt(iy);
  380. if (FAILED(hr))
  381. goto exit;
  382. exit:
  383. return hr;
  384. }
  385. //---------------------------------------------------------------------------
  386. HRESULT CNtlParser::ParseEmitRect()
  387. {
  388. HRESULT hr = S_OK;
  389. int iValue;
  390. for (int i=0; i < 4; i++)
  391. {
  392. if (! _scan.GetNumber(&iValue))
  393. {
  394. hr = SourceError(IDS_INT_EXPECTED);
  395. goto exit;
  396. }
  397. hr = EmitInt(iValue);
  398. if (FAILED(hr))
  399. goto exit;
  400. }
  401. exit:
  402. return hr;
  403. }
  404. //---------------------------------------------------------------------------
  405. HRESULT CNtlParser::ParseEmitSize2()
  406. {
  407. HRESULT hr = ParseEmitSize(); // first size
  408. if (FAILED(hr))
  409. goto exit;
  410. if (_scan.GetChar(','))
  411. {
  412. hr = ParseEmitSize(); // second size
  413. if (FAILED(hr))
  414. goto exit;
  415. }
  416. exit:
  417. return hr;
  418. }
  419. //---------------------------------------------------------------------------
  420. HRESULT CNtlParser::ParseEmitSize4()
  421. {
  422. HRESULT hr = ParseEmitSize(); // first size
  423. if (FAILED(hr))
  424. goto exit;
  425. if (_scan.GetChar(','))
  426. {
  427. hr = ParseEmitSize(); // second size
  428. if (FAILED(hr))
  429. goto exit;
  430. if (_scan.GetChar(','))
  431. {
  432. hr = ParseEmitSize(); // third size
  433. if (FAILED(hr))
  434. goto exit;
  435. if (! _scan.GetChar(','))
  436. {
  437. hr = SourceError(IDS_COMMA_EXPECTED);
  438. goto exit;
  439. }
  440. hr = ParseEmitSize(); // forth size
  441. if (FAILED(hr))
  442. goto exit;
  443. }
  444. }
  445. exit:
  446. return hr;
  447. }
  448. //---------------------------------------------------------------------------
  449. HRESULT CNtlParser::ParseEmitSize()
  450. {
  451. HRESULT hr = S_OK;
  452. int iValue;
  453. WCHAR szId[_MAX_PATH+1];
  454. if (_scan.GetNumber(&iValue))
  455. {
  456. hr = EmitInt(iValue);
  457. if (FAILED(hr))
  458. goto exit;
  459. }
  460. else if (_scan.GetId(szId))
  461. {
  462. int cnt = ARRAYSIZE(pszSysMetricIntNames);
  463. for (SHORT i=0; i < cnt; i++)
  464. {
  465. if (lstrcmpi(szId, pszSysMetricIntNames[i])==0)
  466. {
  467. hr = EmitByte(PT_SYSMETRICINDEX);
  468. if (FAILED(hr))
  469. goto exit;
  470. hr = EmitShort(i);
  471. if (FAILED(hr))
  472. goto exit;
  473. break;
  474. }
  475. if (i == cnt)
  476. {
  477. hr = SourceError(IDS_SIZE_EXPECTED);
  478. goto exit;
  479. }
  480. }
  481. }
  482. else
  483. hr = SourceError(IDS_SIZE_EXPECTED);
  484. exit:
  485. return hr;
  486. }
  487. //---------------------------------------------------------------------------
  488. HRESULT CNtlParser::ParseEmitImagefile()
  489. {
  490. HRESULT hr = S_OK;
  491. int iIndex;
  492. if (! _scan.GetNumber(&iIndex))
  493. iIndex = 0;
  494. //---- emit imagefile ----
  495. hr = EmitByte(PT_IMAGEFILE);
  496. if (FAILED(hr))
  497. goto exit;
  498. hr = EmitByte((BYTE)iIndex);
  499. if (FAILED(hr))
  500. goto exit;
  501. exit:
  502. return hr;
  503. }
  504. //---------------------------------------------------------------------------
  505. HRESULT CNtlParser::ParseEmitColor4()
  506. {
  507. HRESULT hr = ParseEmitColor(); // first color
  508. if (FAILED(hr))
  509. goto exit;
  510. if (_scan.GetChar(','))
  511. {
  512. hr = ParseEmitColor(); // second color
  513. if (FAILED(hr))
  514. goto exit;
  515. if (_scan.GetChar(','))
  516. {
  517. hr = ParseEmitColor(); // third color
  518. if (FAILED(hr))
  519. goto exit;
  520. if (! _scan.GetChar(','))
  521. {
  522. hr = SourceError(IDS_COMMA_EXPECTED);
  523. goto exit;
  524. }
  525. hr = ParseEmitColor(); // forth color
  526. if (FAILED(hr))
  527. goto exit;
  528. }
  529. }
  530. exit:
  531. return hr;
  532. }
  533. //---------------------------------------------------------------------------
  534. HRESULT CNtlParser::ParseEmitColor()
  535. {
  536. HRESULT hr = S_OK;
  537. int iRed, iGreen, iBlue;
  538. WCHAR szColorId[_MAX_PATH+1];
  539. if (_scan.GetNumber(&iRed)) // RGB numbers specified
  540. {
  541. hr = EmitByte(PT_COLORREF);
  542. if (FAILED(hr))
  543. goto exit;
  544. if (! _scan.GetNumber(&iGreen))
  545. {
  546. hr = SourceError(IDS_INT_EXPECTED);
  547. goto exit;
  548. }
  549. if (! _scan.GetNumber(&iBlue))
  550. {
  551. hr = SourceError(IDS_INT_EXPECTED);
  552. goto exit;
  553. }
  554. COLORREF cr = RGB(iRed, iGreen, iBlue);
  555. hr = EmitInt(cr);
  556. if (FAILED(hr))
  557. goto exit;
  558. }
  559. else if (_scan.GetId(szColorId))
  560. {
  561. if (lstrcmpi(szColorId, L"NONE"))
  562. hr = EmitByte(PT_COLORNULL);
  563. else
  564. {
  565. for (SHORT i=0; i < iSysColorSize; i++)
  566. {
  567. if (lstrcmpi(szColorId, pszSysColorNames[i])==0)
  568. {
  569. hr = EmitByte(PT_SYSCOLORINDEX);
  570. if (SUCCEEDED(hr))
  571. hr = EmitShort(i);
  572. break;
  573. }
  574. }
  575. if (i == iSysColorSize)
  576. hr = SourceError(IDS_COLORVALUE_EXPECTED);
  577. }
  578. }
  579. else
  580. hr = SourceError(IDS_COLORVALUE_EXPECTED);
  581. exit:
  582. return hr;
  583. }
  584. //---------------------------------------------------------------------------
  585. HRESULT CNtlParser::ParseEmitNone()
  586. {
  587. HRESULT hr = EmitByte(PT_COLORNULL);
  588. return hr;
  589. }
  590. //---------------------------------------------------------------------------
  591. HRESULT CNtlParser::ParseAddBorder()
  592. {
  593. HRESULT hr = S_OK;
  594. while (SUCCEEDED(hr))
  595. {
  596. if (_scan.GetKeyword(L"SIZE"))
  597. {
  598. hr = ParseEmitSize4();
  599. }
  600. else if (_scan.GetKeyword(L"COLOR"))
  601. {
  602. hr = ParseEmitColor4();
  603. }
  604. else
  605. break;
  606. }
  607. return hr;
  608. }
  609. //---------------------------------------------------------------------------
  610. HRESULT CNtlParser::ParseFillBorder()
  611. {
  612. HRESULT hr = S_OK;
  613. while (SUCCEEDED(hr))
  614. {
  615. if (_scan.GetKeyword(L"COLOR"))
  616. {
  617. hr = ParseEmitColor();
  618. }
  619. else if (_scan.GetKeyword(L"IMAGEFILE"))
  620. {
  621. hr = ParseEmitImagefile();
  622. }
  623. else if (_scan.GetKeyword(L"NONE"))
  624. {
  625. hr = ParseEmitNone();
  626. }
  627. else
  628. break;
  629. }
  630. return hr;
  631. }
  632. //---------------------------------------------------------------------------
  633. HRESULT CNtlParser::ParseFillBrush()
  634. {
  635. HRESULT hr;
  636. hr = EmitByte(NTL_FILLBRUSH);
  637. while (SUCCEEDED(hr))
  638. {
  639. if (_scan.GetKeyword(L"COLOR"))
  640. {
  641. hr = ParseEmitColor();
  642. }
  643. else if (_scan.GetKeyword(L"IMAGEFILE"))
  644. {
  645. hr = ParseEmitImagefile();
  646. }
  647. else if (_scan.GetKeyword(L"NONE"))
  648. {
  649. hr = ParseEmitNone();
  650. }
  651. else
  652. break;
  653. }
  654. return hr;
  655. }
  656. //---------------------------------------------------------------------------
  657. HRESULT CNtlParser::ParseLineBrush()
  658. {
  659. HRESULT hr;
  660. hr = EmitByte(NTL_LINEBRUSH);
  661. if (_scan.GetKeyword(L"NONE"))
  662. {
  663. hr = ParseEmitNone();
  664. }
  665. else
  666. {
  667. while (SUCCEEDED(hr))
  668. {
  669. if (_scan.GetKeyword(L"COLOR"))
  670. {
  671. hr = ParseEmitColor();
  672. }
  673. else if (_scan.GetKeyword(L"SIZE"))
  674. {
  675. hr = ParseEmitSize();
  676. }
  677. else
  678. break;
  679. }
  680. }
  681. return hr;
  682. }
  683. //---------------------------------------------------------------------------
  684. HRESULT CNtlParser::ParseMoveTo()
  685. {
  686. HRESULT hr;
  687. hr = EmitByte(NTL_MOVETO);
  688. if (SUCCEEDED(hr))
  689. {
  690. if (! _scan.GetKeyword(L"POINT"))
  691. hr = SourceError(IDS_POINT_EXPECTED);
  692. else
  693. hr = ParseEmitPoint();
  694. }
  695. return hr;
  696. }
  697. //---------------------------------------------------------------------------
  698. HRESULT CNtlParser::ParseLineTo()
  699. {
  700. HRESULT hr;
  701. hr = EmitByte(NTL_LINETO);
  702. if (SUCCEEDED(hr))
  703. {
  704. if (! _scan.GetKeyword(L"POINT"))
  705. hr = SourceError(IDS_POINT_EXPECTED);
  706. else
  707. hr = ParseEmitPoint();
  708. }
  709. return hr;
  710. }
  711. //---------------------------------------------------------------------------
  712. HRESULT CNtlParser::ParseCurveTo()
  713. {
  714. HRESULT hr;
  715. hr = EmitByte(NTL_CURVETO);
  716. if (SUCCEEDED(hr))
  717. {
  718. if (! _scan.GetKeyword(L"POINT"))
  719. hr = SourceError(IDS_POINT_EXPECTED);
  720. }
  721. if (SUCCEEDED(hr))
  722. hr = ParseEmitPoint();
  723. if (SUCCEEDED(hr))
  724. hr = ParseEmitPoint();
  725. if (SUCCEEDED(hr))
  726. hr = ParseEmitPoint();
  727. return hr;
  728. }
  729. //---------------------------------------------------------------------------
  730. HRESULT CNtlParser::ParseShape()
  731. {
  732. HRESULT hr;
  733. hr = EmitByte(NTL_SHAPE);
  734. if (SUCCEEDED(hr))
  735. {
  736. if (! _scan.GetKeyword(L"POINT"))
  737. hr = SourceError(IDS_POINT_EXPECTED);
  738. }
  739. if (SUCCEEDED(hr))
  740. hr = ParseEmitPoint();
  741. return hr;
  742. }
  743. //---------------------------------------------------------------------------
  744. HRESULT CNtlParser::ParseEndShape()
  745. {
  746. HRESULT hr;
  747. hr = EmitByte(NTL_ENDSHAPE);
  748. if (SUCCEEDED(hr))
  749. {
  750. if (! _scan.GetKeyword(L"POINT"))
  751. hr = SourceError(IDS_POINT_EXPECTED);
  752. }
  753. if (SUCCEEDED(hr))
  754. hr = ParseEmitPoint();
  755. return hr;
  756. }
  757. //---------------------------------------------------------------------------
  758. HRESULT CNtlParser::ParseIf()
  759. {
  760. HRESULT hr = S_OK;
  761. WCHAR szId[_MAX_PATH+1];
  762. NTL_OPCODE opcode;
  763. IFRECORD ifrec;
  764. if (! _scan.GetId(szId))
  765. {
  766. hr = SourceError(IDS_OPTIONNAME_EXPECTED);
  767. goto exit;
  768. }
  769. BYTE iBitnum;
  770. hr = GetBitnumVal(szId, &iBitnum);
  771. if (FAILED(hr))
  772. goto exit;
  773. if (! _scan.GetChar('('))
  774. {
  775. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  776. goto exit;
  777. }
  778. if (_scan.GetKeyword(L"on"))
  779. {
  780. opcode = NTL_JMPOFF;
  781. }
  782. else if (_scan.GetKeyword(L"off"))
  783. {
  784. opcode = NTL_JMPON;
  785. }
  786. else
  787. {
  788. hr = SourceError(IDS_ONOFF_EXPECTED);
  789. goto exit;
  790. }
  791. if (! _scan.GetChar(')'))
  792. {
  793. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  794. goto exit;
  795. }
  796. hr = EmitByte(static_cast<BYTE>(opcode));
  797. if (FAILED(hr))
  798. goto exit;
  799. hr = EmitByte(iBitnum);
  800. if (FAILED(hr))
  801. goto exit;
  802. //---- create a new active IFRECORD ----
  803. if (_iIfLevel == MAX_IF_NESTING)
  804. {
  805. hr = SourceError(IDS_MAX_IFNESTING);
  806. goto exit;
  807. }
  808. ifrec.iBitNum = iBitnum;
  809. ifrec.fIfOn = (opcode == NTL_JMPOFF);
  810. ifrec.iIfOffset = (int)(_u.pb - _pPCode);
  811. ifrec.iElseOffset = 0;
  812. _IfStack[_iIfLevel++] = ifrec;
  813. //---- emit the jump offset ----
  814. hr = EmitInt(0); // will be fixed up later
  815. if (FAILED(hr))
  816. goto exit;
  817. exit:
  818. return hr;
  819. }
  820. //---------------------------------------------------------------------------
  821. HRESULT CNtlParser::ParseElse()
  822. {
  823. HRESULT hr = S_OK;
  824. WCHAR szId[_MAX_PATH+1];
  825. if (! _scan.GetId(szId))
  826. {
  827. hr = SourceError(IDS_OPTIONNAME_EXPECTED);
  828. goto exit;
  829. }
  830. BYTE iBitnum;
  831. hr = GetBitnumVal(szId, &iBitnum);
  832. if (FAILED(hr))
  833. goto exit;
  834. if (! _scan.GetChar('('))
  835. {
  836. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  837. goto exit;
  838. }
  839. BOOL fElseOn;
  840. if (_scan.GetKeyword(L"on"))
  841. {
  842. fElseOn = TRUE;
  843. }
  844. else if (_scan.GetKeyword(L"off"))
  845. {
  846. fElseOn = FALSE;
  847. }
  848. else
  849. {
  850. hr = SourceError(IDS_ONOFF_EXPECTED);
  851. goto exit;
  852. }
  853. if (! _scan.GetChar(')'))
  854. {
  855. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  856. goto exit;
  857. }
  858. //---- emit the JMP ----
  859. hr = EmitByte(NTL_JMP);
  860. if (FAILED(hr))
  861. goto exit;
  862. //---- validate the IFRECORD ----
  863. if (! _iIfLevel)
  864. {
  865. hr = SourceError(IDS_NOMATCHINGIF);
  866. goto exit;
  867. }
  868. IFRECORD *ifrec;
  869. ifrec = &_IfStack[_iIfLevel - 1];
  870. if (ifrec->iBitNum != iBitnum)
  871. {
  872. hr = SourceError(IDS_WRONG_IF_BITNAME);
  873. goto exit;
  874. }
  875. if (ifrec->fIfOn == fElseOn)
  876. {
  877. hr = SourceError(IDS_WRONG_ELSE_PARAM);
  878. goto exit;
  879. }
  880. //---- update the IFRECORD ----
  881. ifrec->iElseOffset = (int)(_u.pb - _pPCode);
  882. //---- emit the jump offset ----
  883. hr = EmitInt(0); // will be fixed up later
  884. //---- fixup the IF jmp ----
  885. int *ip;
  886. ip = (int *)(_pPCode + ifrec->iIfOffset);
  887. *ip = (int)(_u.pb - _pPCode); // point to next instruction
  888. ifrec->iIfOffset = 0; // update no longer needed
  889. exit:
  890. return hr;
  891. }
  892. //---------------------------------------------------------------------------
  893. HRESULT CNtlParser::ParseEndIf()
  894. {
  895. HRESULT hr = S_OK;
  896. WCHAR szId[_MAX_PATH+1];
  897. if (! _scan.GetId(szId))
  898. {
  899. hr = SourceError(IDS_OPTIONNAME_EXPECTED);
  900. goto exit;
  901. }
  902. BYTE iBitnum;
  903. hr = GetBitnumVal(szId, &iBitnum);
  904. if (FAILED(hr))
  905. goto exit;
  906. //---- validate the IFRECORD ----
  907. if (! _iIfLevel)
  908. {
  909. hr = SourceError(IDS_NOMATCHINGIF);
  910. goto exit;
  911. }
  912. IFRECORD *ifrec;
  913. ifrec = &_IfStack[_iIfLevel - 1];
  914. if (ifrec->iBitNum != iBitnum)
  915. {
  916. hr = SourceError(IDS_WRONG_IF_BITNAME);
  917. goto exit;
  918. }
  919. //---- fixup where needed ----
  920. int *ip;
  921. if (ifrec->iIfOffset)
  922. ip = (int *)(_pPCode + ifrec->iIfOffset);
  923. else
  924. ip = (int *)(_pPCode + ifrec->iElseOffset);
  925. *ip = (int)(_u.pb - _pPCode); // point to next instruction
  926. _iIfLevel--;
  927. exit:
  928. return hr;
  929. }
  930. //---------------------------------------------------------------------------
  931. HRESULT CNtlParser::ParseSetOption()
  932. {
  933. HRESULT hr = S_OK;
  934. WCHAR szId[_MAX_PATH+1];
  935. if (! _scan.GetId(szId))
  936. {
  937. hr = SourceError(IDS_OPTIONNAME_EXPECTED);
  938. goto exit;
  939. }
  940. BYTE iBitnum;
  941. hr = GetBitnumVal(szId, &iBitnum);
  942. if (FAILED(hr))
  943. goto exit;
  944. if (! _scan.GetChar('('))
  945. {
  946. hr = SourceError(IDS_LEFTPAREN_EXPECTED);
  947. goto exit;
  948. }
  949. BYTE opcode;
  950. if (_scan.GetKeyword(L"on"))
  951. {
  952. opcode = NTL_SETOPTION;
  953. }
  954. else if (_scan.GetKeyword(L"off"))
  955. {
  956. opcode = NTL_CLROPTION;
  957. }
  958. else
  959. {
  960. hr = SourceError(IDS_ONOFF_EXPECTED);
  961. goto exit;
  962. }
  963. hr = EmitByte(opcode);
  964. if (FAILED(hr))
  965. goto exit;
  966. hr = EmitByte(iBitnum);
  967. exit:
  968. return hr;
  969. }
  970. //---------------------------------------------------------------------------
  971. HRESULT CNtlParser::ParseGotoState()
  972. {
  973. HRESULT hr = S_OK;
  974. WCHAR szId[_MAX_PATH+1];
  975. if (! _scan.GetId(szId))
  976. {
  977. hr = SourceError(IDS_STATEID_EXPECTED);
  978. goto exit;
  979. }
  980. BYTE iStateNum;
  981. hr = GetStateNum(szId, &iStateNum);
  982. if (FAILED(hr))
  983. goto exit;
  984. if ((iStateNum < 1) || (iStateNum > MAX_STATES))
  985. {
  986. hr = SourceError(IDS_BAD_STATENUM);
  987. goto exit;
  988. }
  989. if (! _iStateOffsets[iStateNum])
  990. {
  991. hr = SourceError(IDS_STATE_MUST_BE_DEFINED, szId);
  992. goto exit;
  993. }
  994. EmitByte(NTL_JMP);
  995. EmitInt(_iStateOffsets[iStateNum]);
  996. exit:
  997. return hr;
  998. }
  999. //---------------------------------------------------------------------------
  1000. HRESULT CNtlParser::GetStateNum(LPCWSTR pszStateName, BYTE *piNum)
  1001. {
  1002. HRESULT hr;
  1003. if (_pCallBack)
  1004. hr = _pCallBack->GetStateNum(pszStateName, piNum);
  1005. else
  1006. {
  1007. hr = MakeError32(ERROR_INTERNAL_ERROR);
  1008. Log(LOG_ERROR, L"CNtlParser::GetStateNum - no callback defined");
  1009. }
  1010. return hr;
  1011. }
  1012. //---------------------------------------------------------------------------