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.

1735 lines
36 KiB

  1. #include "precomp.h"
  2. typedef struct
  3. {
  4. eKEYWORD eKey;
  5. char *szzAliases; // Multi-sz string of aliases.
  6. // First one is the "official" name.
  7. } KEYWORDREC;
  8. KEYWORDREC rgKeywords[] =
  9. {
  10. {keywordHELP, "help\0"},
  11. {keywordDUMP_TYPE, "dt\0"},
  12. {keywordDUMP_GLOBALS, "dg\0"},
  13. {keywordL, "L\0"},
  14. {keywordNULL, NULL} // sentinel, must be last.
  15. };
  16. //
  17. // Contains the list of tokens created by parsing an input string.
  18. //
  19. typedef struct
  20. {
  21. TOKEN *rgToks;
  22. UINT cToks;
  23. UINT uNextFreeTok;
  24. UINT uCurrentTok;
  25. char *rgStringBuf;
  26. UINT cchStringBuf;
  27. UINT uNextFree;
  28. BOOL fFinalized;
  29. CRITICAL_SECTION crit;
  30. } TOKLIST;
  31. DBGCOMMAND *
  32. parse_command(TOKLIST *pTL, NAMESPACE *pNameSpace);
  33. TOKLIST
  34. *toklist_create(void);
  35. void
  36. toklist_destroy(TOKLIST *pTL);
  37. BOOL
  38. toklist_add(TOKLIST *pTL, eTOKTYPE eTok, char *szOrig, UINT uID);
  39. BOOL
  40. toklist_finalize(TOKLIST *pTL);
  41. TOKEN *
  42. toklist_get_next(TOKLIST *pTL);
  43. BOOL
  44. toklist_restart(TOKLIST *pTL);
  45. void
  46. toklist_dump(TOKLIST *pTL);
  47. void
  48. tok_dump(TOKEN *pTok);
  49. UINT
  50. toklist_tokenize(TOKLIST *pTL, char *szInput);
  51. UINT
  52. toklist_parse_keyword(
  53. TOKLIST *pTL,
  54. KEYWORDREC rgKeywords[],
  55. char *pcInput
  56. );
  57. UINT
  58. toklist_parse_hexnum(
  59. TOKLIST *pTL,
  60. char *pcInput
  61. );
  62. UINT
  63. toklist_parse_identifier(
  64. TOKLIST *pTL,
  65. char *pcInput
  66. );
  67. BOOL
  68. cmd_parse_help(
  69. DBGCOMMAND *pCmd,
  70. TOKLIST *pTL
  71. );
  72. BOOL
  73. tok_try_force_to_ident(TOKLIST *pTL, BOOL fPrefixStar, TOKEN *pTok);
  74. void
  75. MyDumpObject (
  76. DBGCOMMAND *pCmd,
  77. TYPE_INFO *pType,
  78. UINT_PTR uAddr,
  79. UINT cbSize,
  80. const char *szDescription
  81. );
  82. ULONG
  83. NodeFunc_DumpType (
  84. UINT_PTR uNodeAddr,
  85. UINT uIndex,
  86. void *pvContext
  87. );
  88. ULONG
  89. NodeFunc_UpdateCache (
  90. UINT_PTR uNodeAddr,
  91. UINT uIndex,
  92. void *pvContext
  93. );
  94. DBGCOMMAND *
  95. Parse(
  96. IN const char *szInput,
  97. IN NAMESPACE *pNameSpace
  98. )
  99. {
  100. TOKLIST *pTL = NULL;
  101. BOOL fRet = FALSE;
  102. DBGCOMMAND *pCmd = NULL;
  103. UINT cbInput = (lstrlenA(szInput)+1)*sizeof(*szInput);
  104. char *szRWInput
  105. = LocalAlloc(LPTR, cbInput);
  106. // MyDbgPrintf("Parse(\"%s\");\n", szInput);
  107. if (szRWInput)
  108. {
  109. CopyMemory(szRWInput, szInput, cbInput);
  110. pTL = toklist_create();
  111. }
  112. if (pTL)
  113. {
  114. #if TEST_TOKLIST_ADD
  115. #if 0
  116. fRet = toklist_add(pTL, tokSTAR, "*", tokSTAR);
  117. fRet = toklist_add(pTL, tokDOT, ".", tokDOT);
  118. fRet = toklist_add(pTL, tokQUESTION, "?", tokQUESTION);
  119. fRet = toklist_add(pTL, tokLBRAC, "[", tokLBRAC);
  120. fRet = toklist_add(pTL, tokRBRAC, "]", tokRBRAC);
  121. fRet = toklist_add(pTL, tokSLASH, "/", tokSLASH);
  122. fRet = toklist_add(pTL, tokKEYWORD, "help", keywordHELP);
  123. fRet = toklist_add(pTL, tokNUMBER, "0x1234", 0x1234);
  124. fRet = toklist_add(pTL, tokIDENTIFIER, "cow", 0);
  125. fRet = toklist_add(pTL, tokSTAR, "*", tokSTAR);
  126. fRet = toklist_add(pTL, tokDOT, ".", tokDOT);
  127. fRet = toklist_add(pTL, tokQUESTION, "?", tokQUESTION);
  128. fRet = toklist_add(pTL, tokLBRAC, "[", tokLBRAC);
  129. fRet = toklist_add(pTL, tokRBRAC, "]", tokRBRAC);
  130. fRet = toklist_add(pTL, tokSLASH, "/", tokSLASH);
  131. fRet = toklist_add(pTL, tokKEYWORD, "help", keywordHELP);
  132. fRet = toklist_add(pTL, tokNUMBER, "0x1234", 0x1234);
  133. fRet = toklist_add(pTL, tokIDENTIFIER, "cow", 0);
  134. #else
  135. char rgInput[] =
  136. // "*.?[]/"
  137. // "help "
  138. // "0x12340 0 1 02 "
  139. // "kelp"
  140. "dt if[*].*handle* 0x324890 L 5"
  141. ;
  142. toklist_tokenize (pTL, rgInput);
  143. #endif
  144. #endif // TEST_TOKLIST_ADD
  145. toklist_tokenize(pTL, szRWInput);
  146. toklist_finalize(pTL);
  147. // toklist_dump(pTL);
  148. pCmd = parse_command(pTL, pNameSpace);
  149. if (!pCmd)
  150. {
  151. toklist_destroy(pTL);
  152. }
  153. pTL = NULL;
  154. }
  155. if (szRWInput)
  156. {
  157. LocalFree(szRWInput);
  158. szRWInput = NULL;
  159. }
  160. return pCmd;
  161. }
  162. void
  163. FreeCommand(
  164. DBGCOMMAND *pCmd
  165. )
  166. {
  167. if (pCmd)
  168. {
  169. TOKLIST *pTL = (TOKLIST*)pCmd->pvContext;
  170. if (pTL)
  171. {
  172. // MyDbgPrintf("FreeCommand:\n");
  173. // toklist_restart(pTL);
  174. // toklist_dump(pTL);
  175. toklist_destroy((TOKLIST*)pCmd->pvContext);
  176. }
  177. ZeroMemory(pCmd, sizeof(*pCmd));
  178. LocalFree(pCmd);
  179. }
  180. }
  181. void
  182. DumpCommand(
  183. DBGCOMMAND *pCmd
  184. )
  185. {
  186. char *szCmd = "";
  187. char *szObjPreStar = "";
  188. char *szObj = "";
  189. char *szObjSufStar = "";
  190. char *szObjVecRange = "";
  191. char *szDot = "";
  192. char *szSubObjPreStar = "";
  193. char *szSubObj = "";
  194. char *szSubObjSufStar = "";
  195. char *szObjAddr = "";
  196. char *szObjCount = "";
  197. char rgVecRange[64];
  198. char rgObjAddr[64];
  199. char rgObjCount[64];
  200. if (!pCmd) goto end;
  201. switch(pCmd->ePrimaryCmd)
  202. {
  203. case cmdDUMP_TYPE: szCmd = "dt"; break;
  204. case cmdDUMP_GLOBALS: szCmd = "dg"; break;
  205. case cmdHELP: szCmd = "help"; break;
  206. default: szCmd = "<unknown>"; break;
  207. }
  208. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX))
  209. {
  210. szObjPreStar = "*";
  211. }
  212. if (pCmd->ptokObject)
  213. {
  214. szObj = pCmd->ptokObject->szStr;
  215. }
  216. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX))
  217. {
  218. szObjSufStar = "*";
  219. }
  220. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_VECTOR_INDEX))
  221. {
  222. wsprintfA(
  223. rgVecRange,
  224. "[%ld,%ld]",
  225. pCmd->uVectorIndexStart,
  226. pCmd->uVectorIndexEnd
  227. );
  228. szObjVecRange = rgVecRange;
  229. }
  230. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_SUBOBJECT))
  231. {
  232. szDot = ".";
  233. }
  234. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_PREFIX))
  235. {
  236. szSubObjPreStar = "*";
  237. }
  238. if (pCmd->ptokSubObject)
  239. {
  240. szSubObj = pCmd->ptokSubObject->szStr;
  241. }
  242. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_SUFFIX))
  243. {
  244. szSubObjSufStar = "*";
  245. }
  246. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_ADDRESS))
  247. {
  248. wsprintf(rgObjAddr, "0x%lx", pCmd->uObjectAddress);
  249. szObjAddr = rgObjAddr;
  250. }
  251. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_COUNT))
  252. {
  253. wsprintf(rgObjCount, " L 0x%lx", pCmd->uObjectCount);
  254. szObjCount = rgObjCount;
  255. }
  256. {
  257. #if 0
  258. MyDbgPrintf(
  259. "\nCOMMAND = {"
  260. "cmd=%lu;"
  261. "F=0x%lx;"
  262. "O=0x%lx;"
  263. "SO=0x%lx;"
  264. "VS=%ld;"
  265. "VE=%ld;"
  266. "OA=0x%lx;"
  267. "OC=%ld;"
  268. "}\n",
  269. pCmd->ePrimaryCmd,
  270. pCmd->uFlags,
  271. pCmd->ptokObject,
  272. pCmd->ptokSubObject,
  273. pCmd->uVectorIndexStart,
  274. pCmd->uVectorIndexEnd,
  275. pCmd->uObjectAddress,
  276. pCmd->uObjectCount
  277. );
  278. #else
  279. MyDbgPrintf(
  280. "COMMAND = \"%s %s%s%s%s%s%s%s%s%s%s\";\n",
  281. szCmd,
  282. szObjPreStar,
  283. szObj,
  284. szObjSufStar,
  285. szObjVecRange,
  286. szDot,
  287. szSubObjPreStar,
  288. szSubObj,
  289. szSubObjSufStar,
  290. szObjAddr,
  291. szObjCount
  292. );
  293. #endif
  294. }
  295. end:
  296. return;
  297. }
  298. #define TL_LOCK(_ptl) EnterCriticalSection(&(_ptl)->crit)
  299. #define TL_UNLOCK(_ptl) LeaveCriticalSection(&(_ptl)->crit)
  300. TOKLIST
  301. *toklist_create(void)
  302. {
  303. TOKLIST *pTL = LocalAlloc(LPTR, sizeof(TOKLIST));
  304. if (pTL)
  305. {
  306. InitializeCriticalSection(&pTL->crit);
  307. }
  308. return pTL;
  309. }
  310. void
  311. toklist_destroy(TOKLIST *pTL)
  312. {
  313. if (pTL)
  314. {
  315. TL_LOCK(pTL);
  316. if (pTL->rgToks)
  317. {
  318. LocalFree(pTL->rgToks);
  319. }
  320. if (pTL->rgStringBuf)
  321. {
  322. LocalFree(pTL->rgStringBuf);
  323. }
  324. DeleteCriticalSection(&pTL->crit);
  325. ZeroMemory(pTL, sizeof(*pTL));
  326. LocalFree(pTL);
  327. }
  328. }
  329. BOOL
  330. toklist_add(TOKLIST *pTL, eTOKTYPE eTok, char *szOrig, UINT uID)
  331. {
  332. BOOL fRet = FALSE;
  333. TOKEN *pTok = NULL;
  334. UINT cch = 0;
  335. char *pc = NULL;
  336. TL_LOCK(pTL);
  337. if (pTL->fFinalized) goto end;
  338. //
  339. // Make sure we've enough space for the token.
  340. //
  341. if (pTL->uNextFreeTok >= pTL->cToks)
  342. {
  343. UINT cNewToks = 2*pTL->cToks+1;
  344. TOKEN *pNewToks = (TOKEN*) LocalAlloc(LPTR, cNewToks*sizeof(*pNewToks));
  345. if (!pNewToks) goto end;
  346. if (pTL->rgToks)
  347. {
  348. CopyMemory(
  349. pNewToks,
  350. pTL->rgToks,
  351. pTL->uNextFreeTok*sizeof(*pNewToks)
  352. );
  353. LocalFree(pTL->rgToks);
  354. }
  355. pTL->rgToks = pNewToks;
  356. pTL->cToks = cNewToks;
  357. }
  358. //
  359. // Now deal with szOrig
  360. //
  361. cch = lstrlenA(szOrig)+1;
  362. if ((pTL->uNextFree+cch+1) > pTL->cchStringBuf) // "+1" because multisz
  363. {
  364. UINT cNewStr = 2*pTL->cchStringBuf+cch+1;
  365. char *pNewStr = LocalAlloc(LPTR, cNewStr*sizeof(*pNewStr));
  366. if (!pNewStr) goto end;
  367. if (pTL->rgStringBuf)
  368. {
  369. CopyMemory(
  370. pNewStr,
  371. pTL->rgStringBuf,
  372. pTL->uNextFree*sizeof(*pNewStr)
  373. );
  374. LocalFree(pTL->rgStringBuf);
  375. //
  376. // Since we've reallocated the string buffer, we must
  377. // now fixup the string pointers in the list of tokens
  378. //
  379. {
  380. TOKEN *pTok = pTL->rgToks;
  381. TOKEN *pTokEnd = pTok + pTL->uNextFreeTok;
  382. for(; pTok<pTokEnd; pTok++)
  383. {
  384. pTok->szStr = pNewStr + (pTok->szStr - pTL->rgStringBuf);
  385. }
  386. }
  387. }
  388. pTL->rgStringBuf = pNewStr;
  389. pTL->cchStringBuf = cNewStr;
  390. }
  391. //
  392. // At this point we know we have enough space...
  393. //
  394. //
  395. // See if we already have this string and if not copy it...
  396. //
  397. {
  398. BOOL fFound = FALSE;
  399. for (pc = pTL->rgStringBuf; *pc; pc+=(lstrlenA(pc)+1))
  400. {
  401. if (!lstrcmpiA(pc, szOrig))
  402. {
  403. // found it
  404. fFound = TRUE;
  405. break;
  406. }
  407. }
  408. if (!fFound)
  409. {
  410. MYASSERT(pTL->uNextFree == (UINT) (pc-pTL->rgStringBuf));
  411. CopyMemory(
  412. pc,
  413. szOrig,
  414. cch*sizeof(*szOrig)
  415. );
  416. pTL->uNextFree += cch;
  417. }
  418. }
  419. if (eTok == tokIDENTIFIER)
  420. {
  421. //
  422. // For this special case we ignore the passed-in uID and
  423. // use instead the offset of the string in our string table.
  424. //
  425. uID = (UINT) (pc - pTL->rgStringBuf);
  426. }
  427. pTok = pTL->rgToks+pTL->uNextFreeTok++;
  428. pTok->eTok = eTok;
  429. pTok->uID = uID;
  430. pTok->szStr = pc;
  431. fRet = TRUE;
  432. end:
  433. TL_UNLOCK(pTL);
  434. return fRet;
  435. }
  436. BOOL
  437. toklist_finalize(TOKLIST *pTL)
  438. {
  439. BOOL fRet = FALSE;
  440. TL_LOCK(pTL);
  441. if (pTL->fFinalized) goto end;
  442. pTL->fFinalized = TRUE;
  443. fRet = TRUE;
  444. end:
  445. TL_UNLOCK(pTL);
  446. return fRet;
  447. }
  448. BOOL
  449. toklist_restart(TOKLIST *pTL)
  450. {
  451. BOOL fRet = FALSE;
  452. TL_LOCK(pTL);
  453. if (!pTL->fFinalized) goto end;
  454. pTL->uCurrentTok = 0;
  455. fRet = TRUE;
  456. end:
  457. TL_UNLOCK(pTL);
  458. return fRet;
  459. }
  460. TOKEN *
  461. toklist_get_next(TOKLIST *pTL)
  462. {
  463. TOKEN *pTok = NULL;
  464. TL_LOCK(pTL);
  465. if (!pTL->fFinalized) goto end;
  466. if (pTL->uCurrentTok >= pTL->uNextFreeTok)
  467. {
  468. MYASSERT(pTL->uCurrentTok == pTL->uNextFreeTok);
  469. goto end;
  470. }
  471. else
  472. {
  473. pTok = pTL->rgToks+pTL->uCurrentTok++;
  474. }
  475. end:
  476. TL_UNLOCK(pTL);
  477. return pTok;
  478. }
  479. void
  480. toklist_dump(TOKLIST *pTL)
  481. {
  482. TL_LOCK(pTL);
  483. MyDbgPrintf(
  484. "\nTOKLIST 0x%08lx = {"
  485. "fFin=%lu cToks=%lu uNextFreeTok=%lu cchStr=%lu uNextFree=%lu"
  486. "}\n",
  487. pTL,
  488. pTL->fFinalized,
  489. pTL->cToks,
  490. pTL->uNextFreeTok,
  491. pTL->cchStringBuf,
  492. pTL->uNextFree
  493. );
  494. if (pTL->fFinalized)
  495. {
  496. TOKEN *pTok = toklist_get_next(pTL);
  497. while(pTok)
  498. {
  499. tok_dump(pTok);
  500. pTok = toklist_get_next(pTL);
  501. }
  502. toklist_restart(pTL);
  503. }
  504. TL_UNLOCK(pTL);
  505. }
  506. void
  507. tok_dump(TOKEN *pTok)
  508. {
  509. MyDbgPrintf(
  510. "\tTOKEN 0x%08lx = {eTok=%lu uID=0x%08lx sz=\"%s\"}\n",
  511. pTok,
  512. pTok->eTok,
  513. pTok->uID,
  514. pTok->szStr
  515. );
  516. }
  517. UINT
  518. toklist_tokenize(TOKLIST *pTL, char *szInput)
  519. {
  520. UINT cTokens = 0;
  521. char *pc = szInput;
  522. char c = 0;
  523. BOOL fRet = FALSE;
  524. for (; (c=*pc)!=0; pc++)
  525. {
  526. switch(c)
  527. {
  528. case '*':
  529. fRet = toklist_add(pTL, tokSTAR, "*", tokSTAR);
  530. continue;
  531. case '.':
  532. fRet = toklist_add(pTL, tokDOT, ".", tokDOT);
  533. continue;
  534. case '?':
  535. fRet = toklist_add(pTL, tokQUESTION, "?", tokQUESTION);
  536. continue;
  537. case '[':
  538. fRet = toklist_add(pTL, tokLBRAC, "[", tokLBRAC);
  539. continue;
  540. case ']':
  541. fRet = toklist_add(pTL, tokRBRAC, "]", tokRBRAC);
  542. continue;
  543. case '/':
  544. fRet = toklist_add(pTL, tokSLASH, "/", tokSLASH);
  545. continue;
  546. case '\n':
  547. case '\r':
  548. case '\t':
  549. case ' ':
  550. continue;
  551. default:
  552. {
  553. UINT uCharsParsed = 0;
  554. char *pcEnd = pc;
  555. char cSave = 0;
  556. //
  557. // We'll locate the end of the potential keyword/number/ident:
  558. // and temprarily place a NULL char there.
  559. //
  560. //
  561. while (__iscsym(*pcEnd))
  562. {
  563. pcEnd++;
  564. }
  565. cSave = *pcEnd;
  566. *pcEnd = 0;
  567. if (__iscsymf(c))
  568. {
  569. // This may be a keyword, hex number or identifier. We try
  570. // in this order
  571. uCharsParsed = toklist_parse_keyword(
  572. pTL,
  573. rgKeywords,
  574. pc
  575. );
  576. if (!uCharsParsed && isxdigit(c))
  577. {
  578. //
  579. // Didn't find a keyword and this is a hex digit --
  580. // let's try to parse it as a hex number...
  581. //
  582. uCharsParsed = toklist_parse_hexnum(pTL, pc);
  583. }
  584. if (!uCharsParsed)
  585. {
  586. //
  587. // Parse it as an identifier...
  588. //
  589. uCharsParsed = toklist_parse_identifier(pTL, pc);
  590. }
  591. if (!uCharsParsed)
  592. {
  593. //
  594. // This is an error
  595. //
  596. MyDbgPrintf("Error at %s\n", pc);
  597. goto end;
  598. }
  599. }
  600. else if (isxdigit(c))
  601. {
  602. uCharsParsed = toklist_parse_hexnum(pTL, pc);
  603. }
  604. //
  605. // If we've parsed anything it should be ALL of the string...
  606. //
  607. MYASSERT(!uCharsParsed || uCharsParsed==(UINT)lstrlenA(pc));
  608. //
  609. // Restore the char we replaced by NULL.
  610. //
  611. *pcEnd = cSave;
  612. if (!uCharsParsed)
  613. {
  614. //
  615. // Syntax error
  616. //
  617. MyDbgPrintf("Error at %s\n", pc);
  618. goto end;
  619. }
  620. else
  621. {
  622. pc+= (uCharsParsed-1); // "-1" because of pc++ in
  623. // for clause above.
  624. }
  625. }
  626. }
  627. }
  628. end:
  629. return cTokens;
  630. }
  631. UINT
  632. toklist_parse_keyword(
  633. TOKLIST *pTL,
  634. KEYWORDREC rgKeywords[],
  635. char *pcInput
  636. )
  637. //
  638. // Assumes 1st char is valid.
  639. //
  640. {
  641. UINT uRet = 0;
  642. KEYWORDREC *pkr = rgKeywords;
  643. if (!__iscsymf(*pcInput)) goto end;
  644. for (;pkr->eKey!=keywordNULL; pkr++)
  645. {
  646. if (!lstrcmpi(pcInput, pkr->szzAliases))
  647. {
  648. //
  649. // found it
  650. //
  651. toklist_add(pTL, tokKEYWORD, pcInput, pkr->eKey);
  652. uRet = lstrlenA(pcInput);
  653. break;
  654. }
  655. }
  656. end:
  657. return uRet;
  658. }
  659. UINT
  660. toklist_parse_hexnum(
  661. TOKLIST *pTL,
  662. char *pcInput
  663. )
  664. {
  665. char *pc = pcInput;
  666. UINT uValue = 0;
  667. char c;
  668. UINT u;
  669. //
  670. // look for and ignore the "0x" prefix...
  671. //
  672. if (pc[0]=='0' && (pc[1]=='x' || pc[1]=='X'))
  673. {
  674. pc+=2;
  675. }
  676. //
  677. // Reject number if it is doesn't contain hex digits or is too large
  678. //
  679. for (u=0; isxdigit(*pc) && u<8; pc++,u++)
  680. {
  681. UINT uDigit = 0;
  682. char c = *pc;
  683. if (!isdigit(c))
  684. {
  685. c = (char) _toupper(c);
  686. uDigit = 10 + c - 'A';
  687. }
  688. else
  689. {
  690. uDigit = c - '0';
  691. }
  692. uValue = (uValue<<4)|uDigit;
  693. }
  694. if (!u || *pc)
  695. {
  696. return 0;
  697. }
  698. else
  699. {
  700. toklist_add(pTL, tokNUMBER, pcInput, uValue);
  701. return pc - pcInput;
  702. }
  703. }
  704. UINT
  705. toklist_parse_identifier(
  706. TOKLIST *pTL,
  707. char *pcInput
  708. )
  709. {
  710. UINT uRet = 0;
  711. if (!__iscsymf(*pcInput)) goto end;
  712. toklist_add(pTL, tokIDENTIFIER, pcInput, 0);
  713. uRet = lstrlenA(pcInput);
  714. end:
  715. return uRet;
  716. }
  717. DBGCOMMAND *
  718. parse_command(TOKLIST *pTL, NAMESPACE *pNameSpace)
  719. {
  720. BOOL fRet = FALSE;
  721. DBGCOMMAND *pCmd = LocalAlloc(LPTR, sizeof(*pCmd));
  722. TOKEN *pTok = NULL;
  723. BOOL fSyntaxError = FALSE;
  724. if (!pCmd) goto end;
  725. toklist_restart(pTL);
  726. pTok = toklist_get_next(pTL);
  727. if (!pTok) goto end;
  728. pCmd->pNameSpace = pNameSpace;
  729. //
  730. // Now let's step through the token list, building up our command
  731. // information.
  732. //
  733. // look for help or ?
  734. if (pTok->eTok == tokQUESTION
  735. || (pTok->eTok == tokKEYWORD && pTok->uID == keywordHELP))
  736. {
  737. pCmd->ePrimaryCmd = cmdHELP;
  738. fRet = cmd_parse_help(pCmd, pTL);
  739. goto end;
  740. }
  741. fSyntaxError = TRUE;
  742. fRet = FALSE;
  743. //
  744. // Here we would look for other keywords. Currently there are none
  745. // (dt and dg are not used anymore).
  746. //
  747. //
  748. #if OBSOLETE
  749. if (pTok->eTok == tokKEYWORD)
  750. {
  751. BOOL fDump = FALSE;
  752. if (pTok->uID == keywordDUMP_TYPE)
  753. {
  754. pCmd->ePrimaryCmd = cmdDUMP_TYPE;
  755. fDump = TRUE;
  756. }
  757. else if (pTok->uID == keywordDUMP_GLOBALS)
  758. {
  759. pCmd->ePrimaryCmd = cmdDUMP_GLOBALS;
  760. fDump = TRUE;
  761. }
  762. ...
  763. }
  764. #endif // OBSOLETE
  765. pCmd->ePrimaryCmd = cmdDUMP_TYPE;
  766. //
  767. // Pares the form a[b].*c* d L e
  768. //
  769. {
  770. BOOL fPrefixStar = FALSE;
  771. // we look for patterns like...
  772. //!aac <type> . <field> <address> L <count> <flags>
  773. //!aac <type> [index] . <field> L <count> <flags>
  774. //
  775. //!aac i[*].*handle* 0x324890 L 5
  776. //[*]ident[*]\[<range>\][.][*]ident[*] <number> [L <number>]
  777. UINT uFlags; // One or more fCMDFLAG_*
  778. TOKEN *ptokObject; // eg <type>
  779. TOKEN *ptokSubObject; // eg <field>
  780. UINT uVectorIndexStart; // if[0]
  781. UINT uVectorIndexEnd; // if[0]
  782. UINT uObjectAddress; // <address>
  783. UINT uObjectCount; // L 10
  784. //
  785. // 1. Look for primary star
  786. //
  787. if (pTok && pTok->eTok == tokSTAR)
  788. {
  789. fPrefixStar = TRUE;
  790. CMD_SET_FLAG(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX);
  791. pTok = toklist_get_next(pTL);
  792. }
  793. //
  794. // 2. Look for ident
  795. //
  796. if (pTok && tok_try_force_to_ident(pTL, fPrefixStar, pTok))
  797. {
  798. //
  799. // This will try to convert keywords and numbers to idents if
  800. // possible.
  801. //
  802. pCmd->ptokObject = pTok;
  803. pTok = toklist_get_next(pTL);
  804. }
  805. //
  806. // 3. Look for suffix * for object.
  807. //
  808. if (pTok && pTok->eTok == tokSTAR)
  809. {
  810. CMD_SET_FLAG(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX);
  811. pTok = toklist_get_next(pTL);
  812. }
  813. //
  814. // 4. Look for Vector Range
  815. //
  816. if (pTok && pTok->eTok == tokLBRAC)
  817. {
  818. //
  819. // For now, we support either a single * or a single number.
  820. //
  821. pTok = toklist_get_next(pTL);
  822. if (!pTok)
  823. {
  824. goto end; // Error -- incomplete vector range
  825. }
  826. else
  827. {
  828. if (pTok->eTok == tokSTAR)
  829. {
  830. pCmd->uVectorIndexStart = 0;
  831. pCmd->uVectorIndexEnd = (UINT) -1;
  832. }
  833. else if (pTok->eTok == tokNUMBER)
  834. {
  835. pCmd->uVectorIndexStart =
  836. pCmd->uVectorIndexEnd = pTok->uID;
  837. }
  838. else
  839. {
  840. goto end; // failure...
  841. }
  842. CMD_SET_FLAG(pCmd, fCMDFLAG_HAS_VECTOR_INDEX);
  843. pTok = toklist_get_next(pTL);
  844. if (!pTok || pTok->eTok != tokRBRAC)
  845. {
  846. goto end; // failure ... expect RBRAC.
  847. }
  848. else
  849. {
  850. pTok = toklist_get_next(pTL);
  851. }
  852. }
  853. }
  854. //
  855. // 5. Look for DOT
  856. //
  857. if (pTok && pTok->eTok == tokDOT)
  858. {
  859. fPrefixStar = FALSE;
  860. pTok = toklist_get_next(pTL);
  861. // We expect ([*]ident[*]|*)
  862. //
  863. // 1. Look for primary star
  864. //
  865. if (pTok && pTok->eTok == tokSTAR)
  866. {
  867. fPrefixStar = TRUE;
  868. CMD_SET_FLAG(pCmd, fCMDFLAG_SUBOBJECT_STAR_PREFIX);
  869. pTok = toklist_get_next(pTL);
  870. }
  871. //
  872. // 2. Look for ident
  873. //
  874. if (pTok && tok_try_force_to_ident(pTL, fPrefixStar, pTok))
  875. {
  876. //
  877. // This will try to convert keywords and numbers to idents if
  878. // possible.
  879. //
  880. pCmd->ptokSubObject = pTok;
  881. pTok = toklist_get_next(pTL);
  882. }
  883. //
  884. // 3. Look for suffix * for object.
  885. //
  886. if (pTok && pTok->eTok == tokSTAR)
  887. {
  888. CMD_SET_FLAG(pCmd, fCMDFLAG_SUBOBJECT_STAR_SUFFIX);
  889. pTok = toklist_get_next(pTL);
  890. }
  891. //
  892. // At this point we should either have a non-null IDENT
  893. // or the PREFIX START should be set for the object
  894. // (indicateing "a.*").
  895. //
  896. if ( pCmd->ptokSubObject
  897. || (pCmd->uFlags & fCMDFLAG_SUBOBJECT_STAR_SUFFIX))
  898. {
  899. CMD_SET_FLAG(pCmd, fCMDFLAG_HAS_SUBOBJECT);
  900. }
  901. else
  902. {
  903. goto end; // error
  904. }
  905. }
  906. //
  907. // 6. Look for object address
  908. //
  909. if (pTok && pTok->eTok == tokNUMBER)
  910. {
  911. pCmd->uObjectAddress = pTok->uID;
  912. CMD_SET_FLAG(pCmd, fCMDFLAG_HAS_OBJECT_ADDRESS);
  913. pTok = toklist_get_next(pTL);
  914. }
  915. //
  916. // 7. Look for object count
  917. //
  918. if ( pTok && pTok->eTok == tokKEYWORD
  919. && pTok->uID == keywordL)
  920. {
  921. pTok = toklist_get_next(pTL);
  922. if (pTok && pTok->eTok == tokNUMBER)
  923. {
  924. pCmd->uObjectCount = pTok->uID;
  925. CMD_SET_FLAG(pCmd, fCMDFLAG_HAS_OBJECT_COUNT);
  926. pTok = toklist_get_next(pTL);
  927. }
  928. else
  929. {
  930. // error
  931. }
  932. }
  933. //
  934. // At this point we should be done...
  935. //
  936. if (pTok)
  937. {
  938. // error -- extra garbage...
  939. }
  940. else
  941. {
  942. // Success.
  943. fRet = TRUE;
  944. fSyntaxError = FALSE;
  945. }
  946. }
  947. end:
  948. if (fRet)
  949. {
  950. pCmd->pvContext = pTL;
  951. }
  952. else
  953. {
  954. if (fSyntaxError)
  955. {
  956. MyDbgPrintf("Unexpected: %s\n", (pTok) ? pTok->szStr : "<null>");
  957. }
  958. else
  959. {
  960. MyDbgPrintf("Parse failed\n");
  961. }
  962. if (pCmd)
  963. {
  964. ZeroMemory(pCmd, sizeof(*pCmd));
  965. LocalFree(pCmd);
  966. pCmd = NULL;
  967. }
  968. }
  969. if (pTL)
  970. {
  971. toklist_restart(pTL);
  972. }
  973. return pCmd;
  974. }
  975. BOOL
  976. cmd_parse_help(
  977. DBGCOMMAND *pCmd,
  978. TOKLIST *pTL
  979. )
  980. {
  981. TOKEN *pTok = toklist_get_next(pTL);
  982. if (!pTok || pTok->eTok == tokSTAR)
  983. {
  984. // User type "help" or "help *"
  985. MyDbgPrintf("DO HELP\n");
  986. }
  987. return TRUE;
  988. }
  989. BOOL
  990. tok_try_force_to_ident(TOKLIST *pTL, BOOL fPrefixStar, TOKEN *pTok)
  991. //
  992. // This gets called when an identifier is expected -- so we see if this
  993. // particular token can be interpreted as in identifier. Some examples
  994. // of when we can do this:
  995. // dt if.*20334 <--- the "20334" could be part of an identifier, because
  996. // of the * prefix.
  997. //
  998. // dt L.help <--- both "L" and "help" would have been parsed as
  999. // keywords, but here they are intended to be
  1000. // identifiers.
  1001. // dt abc.def <--- abc and def would have been parsed as numbers (they
  1002. // are valid hex numbers), but are intended to be
  1003. // identifiers.
  1004. {
  1005. BOOL fRet = FALSE;
  1006. switch(pTok->eTok)
  1007. {
  1008. case tokNUMBER:
  1009. //
  1010. // We could do this, but subject to some restrictions...
  1011. //
  1012. if (!__iscsymf(pTok->szStr[0]) && !fPrefixStar)
  1013. {
  1014. break; // Can't to this: no prefix wild-card (*) and the
  1015. // number starts with a non-letter.
  1016. }
  1017. // FALL THROUGH ...
  1018. case tokKEYWORD:
  1019. //
  1020. // We can go ahead, but we must make pTok.uID now the offset
  1021. // from the start of the internal string array.
  1022. //
  1023. {
  1024. char *pc = pTL->rgStringBuf;
  1025. for (; *pc; pc+=(lstrlenA(pc)+1))
  1026. {
  1027. if (!lstrcmpiA(pc, pTok->szStr))
  1028. {
  1029. // found it
  1030. // MyDbgPrintf("FORCE_TO_IDENT:\nOLD:\n");
  1031. // tok_dump(pTok);
  1032. pTok->uID = (UINT) (pc - pTL->rgStringBuf);
  1033. pTok->eTok = tokIDENTIFIER;
  1034. // MyDbgPrintf("NEW:\n");
  1035. // tok_dump(pTok);
  1036. fRet = TRUE;
  1037. break;
  1038. }
  1039. }
  1040. }
  1041. break;
  1042. case tokIDENTIFIER:
  1043. //
  1044. // nothing to do...
  1045. //
  1046. fRet = TRUE;
  1047. break;
  1048. default:
  1049. //
  1050. // Can't convert any other kind of token to identifier...
  1051. //
  1052. break;
  1053. }
  1054. return fRet;
  1055. }
  1056. void
  1057. DoCommand(DBGCOMMAND *pCmd, PFN_SPECIAL_COMMAND_HANDLER pfnHandler)
  1058. {
  1059. char *szMsg = NULL;
  1060. // pCmd->pfnSpecialHandler = pfnHandler;
  1061. switch(pCmd->ePrimaryCmd)
  1062. {
  1063. case cmdDUMP_TYPE:
  1064. DoDumpType(pCmd);
  1065. break;
  1066. case cmdDUMP_GLOBALS:
  1067. DoDumpGlobals(pCmd);
  1068. break;
  1069. case cmdHELP:
  1070. DoHelp(pCmd);
  1071. break;
  1072. default:
  1073. szMsg = "Unknown command\n";
  1074. break;
  1075. }
  1076. if (szMsg)
  1077. {
  1078. MyDbgPrintf(szMsg);
  1079. }
  1080. return;
  1081. }
  1082. typedef struct
  1083. {
  1084. DBGCOMMAND *pCmd;
  1085. TYPE_INFO *pType;
  1086. } MY_LIST_NODE_CONTEXT;
  1087. typedef
  1088. ULONG
  1089. MyDumpListNode (
  1090. UINT_PTR uNodeAddr,
  1091. UINT uIndex,
  1092. void *pvContext
  1093. );
  1094. void
  1095. DoDumpType(DBGCOMMAND *pCmd)
  1096. {
  1097. char *szPattern = NULL;
  1098. PFNMATCHINGFUNCTION pfnMatchingFunction = MatchAlways;
  1099. TYPE_INFO **ppti = NULL;
  1100. UINT uMatchCount = 0;
  1101. TYPE_INFO *ptiDump = NULL;
  1102. //
  1103. // Pick a selection function ...
  1104. //
  1105. if (pCmd->ptokObject)
  1106. {
  1107. szPattern = pCmd->ptokObject->szStr;
  1108. if ( CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX)
  1109. &&CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX))
  1110. {
  1111. pfnMatchingFunction = MatchSubstring;
  1112. }
  1113. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX))
  1114. {
  1115. pfnMatchingFunction = MatchSuffix;
  1116. }
  1117. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX))
  1118. {
  1119. pfnMatchingFunction = MatchPrefix;
  1120. }
  1121. else
  1122. {
  1123. pfnMatchingFunction = MatchExactly;
  1124. }
  1125. }
  1126. //
  1127. // search through global type array for type pName.
  1128. //
  1129. for(ppti=pCmd->pNameSpace->pTypes;*ppti;ppti++)
  1130. {
  1131. TYPE_INFO *pti = *ppti;
  1132. bool fMatch = !szPattern
  1133. || !_stricmp(szPattern, pti->szShortName)
  1134. || pfnMatchingFunction(szPattern, pti->szName);
  1135. if (fMatch)
  1136. {
  1137. #if 0
  1138. MyDbgPrintf(
  1139. "TYPE \"%2s\" %s (%lu Bytes)\n",
  1140. pti->szShortName,
  1141. pti->szName,
  1142. pti->cbSize
  1143. );
  1144. #endif // 0
  1145. uMatchCount++;
  1146. if (!ptiDump)
  1147. {
  1148. ptiDump = pti;
  1149. }
  1150. #if 0
  1151. uAddr =
  1152. MyDbgPrintf(
  1153. "dc 0x%08lx L %03lx \"%2s\" %s\n",
  1154. pgi->uAddr,
  1155. pgi->cbSize,
  1156. pgi->szShortName,
  1157. pgi->szName
  1158. );
  1159. if (szPattern && pgi->uAddr)
  1160. {
  1161. MyDumpObject(
  1162. pCmd,
  1163. pgi->pBaseType,
  1164. pgi->uAddr,
  1165. pgi->cbSize,
  1166. pgi->szName
  1167. );
  1168. }
  1169. #endif // 0
  1170. }
  1171. }
  1172. if (!uMatchCount)
  1173. {
  1174. MyDbgPrintf(
  1175. "Could not find type \"%s\"",
  1176. (szPattern ? szPattern : "*")
  1177. );
  1178. }
  1179. else if ( uMatchCount==1)
  1180. {
  1181. UINT uObjectCount = 1;
  1182. UINT uStartIndex = 0;
  1183. UINT uObjectAddress = 0;
  1184. BOOLEAN fList = TYPEISLIST(ptiDump)!=0;
  1185. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_ADDRESS))
  1186. {
  1187. uObjectAddress = pCmd->uObjectAddress;
  1188. }
  1189. //
  1190. // Determine start index.
  1191. //
  1192. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_VECTOR_INDEX))
  1193. {
  1194. uStartIndex = pCmd->uVectorIndexStart;
  1195. if (fList && !CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_COUNT))
  1196. {
  1197. uObjectCount = pCmd->uVectorIndexEnd - uStartIndex;
  1198. if (uObjectCount != (UINT) -1)
  1199. {
  1200. uObjectCount++;
  1201. }
  1202. }
  1203. }
  1204. //
  1205. // Determine object count...
  1206. //
  1207. if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_COUNT))
  1208. {
  1209. uObjectCount = pCmd->uObjectCount;
  1210. }
  1211. //
  1212. // If no address is specified, we'll try to resolve it ...
  1213. //
  1214. if (!CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_OBJECT_ADDRESS))
  1215. {
  1216. BOOLEAN fUseCache = FALSE;
  1217. //
  1218. // Algorithm for determining whether to use cache or to resolve
  1219. // address:
  1220. //
  1221. if (ptiDump->uCachedAddress)
  1222. {
  1223. //
  1224. // Except for the special case of [0], we will use
  1225. // the the cached value.
  1226. //
  1227. if (!( uStartIndex ==0
  1228. && uObjectCount==1
  1229. && CMD_IS_FLAG_SET(pCmd, fCMDFLAG_HAS_VECTOR_INDEX)))
  1230. {
  1231. fUseCache = TRUE;
  1232. }
  1233. }
  1234. if (fUseCache)
  1235. {
  1236. uObjectAddress = ptiDump->uCachedAddress;
  1237. }
  1238. else
  1239. {
  1240. if (pCmd->pNameSpace->pfnResolveAddress)
  1241. {
  1242. uObjectAddress = pCmd->pNameSpace->pfnResolveAddress(
  1243. ptiDump
  1244. );
  1245. }
  1246. }
  1247. }
  1248. if (uObjectAddress && uObjectCount)
  1249. {
  1250. //
  1251. // Prune these to "reasonable" values.
  1252. //
  1253. if (uObjectCount > 100)
  1254. {
  1255. MyDbgPrintf("Limiting object count to 100\n");
  1256. uObjectCount = 100;
  1257. }
  1258. if (fList)
  1259. {
  1260. MY_LIST_NODE_CONTEXT Context;
  1261. Context.pCmd = pCmd;
  1262. Context.pType = ptiDump;
  1263. WalkList(
  1264. uObjectAddress, // start address
  1265. ptiDump->uNextOffset, // next offset
  1266. uStartIndex,
  1267. uStartIndex+uObjectCount-1, // end index
  1268. &Context, // context
  1269. NodeFunc_DumpType, // function
  1270. (char *) ptiDump->szName
  1271. );
  1272. //
  1273. // If only a single structure was dumped, and it was dumped
  1274. // successfully, we will update this structure's cache.
  1275. // TODO: we don't check for success
  1276. //
  1277. if (uObjectCount==1)
  1278. {
  1279. WalkList(
  1280. uObjectAddress, // start address
  1281. ptiDump->uNextOffset, // next offset
  1282. uStartIndex,
  1283. uStartIndex, // end index
  1284. ptiDump, // context
  1285. NodeFunc_UpdateCache, // function
  1286. (char *) ptiDump->szName
  1287. );
  1288. }
  1289. }
  1290. else
  1291. {
  1292. UINT cbSize = ptiDump->cbSize;
  1293. UINT uAddr = uObjectAddress + uStartIndex*cbSize;
  1294. UINT uEnd = uAddr + uObjectCount*cbSize;
  1295. //
  1296. // For arays, compute offset to start address
  1297. //
  1298. uObjectAddress = uAddr;
  1299. for (; uAddr<uEnd; uAddr+=cbSize)
  1300. {
  1301. MyDumpObject(
  1302. pCmd,
  1303. ptiDump,
  1304. uAddr,
  1305. ptiDump->cbSize,
  1306. ptiDump->szName
  1307. );
  1308. }
  1309. //
  1310. // If only a single structure was dumped, and it was dumped
  1311. // successfully, we will update this structure's cache.
  1312. // TODO: we don't check for success
  1313. //
  1314. if (uObjectCount==1)
  1315. {
  1316. ptiDump->uCachedAddress = uObjectAddress;
  1317. }
  1318. }
  1319. }
  1320. else
  1321. {
  1322. MyDbgPrintf(
  1323. "Could not resolve address for object %s\n",
  1324. ptiDump->szName
  1325. );
  1326. }
  1327. }
  1328. }
  1329. void
  1330. DoDumpGlobals(DBGCOMMAND *pCmd)
  1331. {
  1332. GLOBALVAR_INFO *pgi = pCmd->pNameSpace->pGlobals;
  1333. char *szPattern = NULL;
  1334. PFNMATCHINGFUNCTION pfnMatchingFunction = MatchAlways;
  1335. //
  1336. // Pick a selection function ...
  1337. //
  1338. if (pCmd->ptokObject)
  1339. {
  1340. szPattern = pCmd->ptokObject->szStr;
  1341. if ( CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX)
  1342. &&CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX))
  1343. {
  1344. pfnMatchingFunction = MatchSubstring;
  1345. }
  1346. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_PREFIX))
  1347. {
  1348. pfnMatchingFunction = MatchSuffix;
  1349. }
  1350. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_OBJECT_STAR_SUFFIX))
  1351. {
  1352. pfnMatchingFunction = MatchPrefix;
  1353. }
  1354. else
  1355. {
  1356. pfnMatchingFunction = MatchExactly;
  1357. }
  1358. }
  1359. //
  1360. // Run through our list of globals, and if the entry is selected,
  1361. // we will display it.
  1362. //
  1363. for (;pgi->szName; pgi++)
  1364. {
  1365. bool fMatch = !szPattern
  1366. || !_stricmp(szPattern, pgi->szShortName)
  1367. || pfnMatchingFunction(szPattern, pgi->szName);
  1368. if (fMatch)
  1369. {
  1370. pgi->uAddr = dbgextGetExpression(pgi->szName);
  1371. MyDbgPrintf(
  1372. "dc 0x%08lx L %03lx \"%2s\" %s\n",
  1373. pgi->uAddr,
  1374. pgi->cbSize,
  1375. pgi->szShortName,
  1376. pgi->szName
  1377. );
  1378. if (szPattern && pgi->uAddr)
  1379. {
  1380. MyDumpObject(
  1381. pCmd,
  1382. pgi->pBaseType,
  1383. pgi->uAddr,
  1384. pgi->cbSize,
  1385. pgi->szName
  1386. );
  1387. }
  1388. }
  1389. }
  1390. }
  1391. void
  1392. DoHelp(
  1393. DBGCOMMAND *pCmd // OPTIONAL
  1394. )
  1395. {
  1396. //
  1397. //
  1398. //
  1399. MyDbgPrintf("help unimplemented\n");
  1400. }
  1401. void
  1402. MyDumpObject (
  1403. DBGCOMMAND *pCmd,
  1404. TYPE_INFO *pType,
  1405. UINT_PTR uAddr,
  1406. UINT cbSize,
  1407. const char *szDescription
  1408. )
  1409. {
  1410. UINT uMatchFlags = 0;
  1411. char *szFieldSpec = NULL;
  1412. if (pCmd->ptokSubObject)
  1413. {
  1414. szFieldSpec = pCmd->ptokSubObject->szStr;
  1415. if ( CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_PREFIX)
  1416. &&CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_SUFFIX))
  1417. {
  1418. uMatchFlags = fMATCH_SUBSTRING;
  1419. }
  1420. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_PREFIX))
  1421. {
  1422. uMatchFlags = fMATCH_SUFFIX;
  1423. }
  1424. else if (CMD_IS_FLAG_SET(pCmd, fCMDFLAG_SUBOBJECT_STAR_SUFFIX))
  1425. {
  1426. uMatchFlags = fMATCH_PREFIX;
  1427. }
  1428. }
  1429. if (!pType)
  1430. {
  1431. DumpMemory(
  1432. uAddr,
  1433. cbSize,
  1434. 0,
  1435. szDescription
  1436. );
  1437. }
  1438. else
  1439. {
  1440. DumpStructure(pType, uAddr, szFieldSpec, uMatchFlags);
  1441. }
  1442. }
  1443. ULONG
  1444. NodeFunc_DumpType (
  1445. UINT_PTR uNodeAddr,
  1446. UINT uIndex,
  1447. void *pvContext
  1448. )
  1449. {
  1450. MY_LIST_NODE_CONTEXT *pContext = (MY_LIST_NODE_CONTEXT*) pvContext;
  1451. MyDbgPrintf("[%lu] ", uIndex);
  1452. MyDumpObject (
  1453. pContext->pCmd,
  1454. pContext->pType,
  1455. uNodeAddr,
  1456. pContext->pType->cbSize,
  1457. pContext->pType->szName
  1458. );
  1459. return 0;
  1460. }
  1461. ULONG
  1462. NodeFunc_UpdateCache (
  1463. UINT_PTR uNodeAddr,
  1464. UINT uIndex,
  1465. void *pvContext
  1466. )
  1467. {
  1468. TYPE_INFO *pti = (TYPE_INFO*) pvContext;
  1469. if (pti->uCachedAddress != uNodeAddr)
  1470. {
  1471. MyDbgPrintf(
  1472. "Updating Cache from 0x%lx to 0x%lx\n",
  1473. pti->uCachedAddress,
  1474. uNodeAddr
  1475. );
  1476. }
  1477. pti->uCachedAddress = uNodeAddr;
  1478. return 0;
  1479. }