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.

1741 lines
36 KiB

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