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.

544 lines
10 KiB

  1. /* Copyright (C) Microsoft Corporation, 1998. All rights reserved. */
  2. #include "precomp.h"
  3. #include "macro.h"
  4. CMacro::
  5. CMacro
  6. (
  7. BOOL *pfRetCode,
  8. LPSTR pszMacroName,
  9. UINT cbMaxBodySize
  10. )
  11. :
  12. m_ArgList(8), // default 8 arguments
  13. m_MacroInstList(16), // default 16 instances of this macro
  14. m_cFormalArgs(0),
  15. m_cbBodySize(0),
  16. m_cbMaxBodySize(cbMaxBodySize),
  17. m_pszExpandBuffer(NULL),
  18. m_fArgExistsInBody(FALSE),
  19. m_fImported(FALSE)
  20. {
  21. m_pszMacroName = ::My_strdup(pszMacroName);
  22. m_pszBodyBuffer = new char[m_cbMaxBodySize];
  23. m_pszCurr = m_pszBodyBuffer;
  24. *pfRetCode = (NULL != m_pszMacroName) &&
  25. (NULL != m_pszBodyBuffer);
  26. }
  27. CMacro::
  28. CMacro
  29. (
  30. BOOL *pfRetCode,
  31. CMacro *pMacro
  32. )
  33. :
  34. m_ArgList(pMacro->m_ArgList.GetCount()), // default 8 arguments
  35. m_MacroInstList(16), // default 16 instances of this macro
  36. m_cFormalArgs(pMacro->m_cFormalArgs),
  37. m_cbBodySize(pMacro->m_cbBodySize),
  38. m_cbMaxBodySize(pMacro->m_cbMaxBodySize),
  39. m_pszExpandBuffer(NULL),
  40. m_fArgExistsInBody(pMacro->m_fArgExistsInBody),
  41. m_fImported(TRUE)
  42. {
  43. m_pszMacroName = ::My_strdup(pMacro->m_pszMacroName);
  44. m_pszBodyBuffer = new char[m_cbMaxBodySize];
  45. if (NULL != m_pszMacroName && NULL != m_pszBodyBuffer)
  46. {
  47. // copy the body
  48. ::memcpy(m_pszBodyBuffer, pMacro->m_pszBodyBuffer, pMacro->m_cbBodySize);
  49. // adjust the current buffer pointer
  50. m_pszCurr = m_pszBodyBuffer + m_cbBodySize;
  51. // null terminated the body
  52. *m_pszCurr++ = '\0';
  53. // set up the expand buffer
  54. m_pszExpandBuffer = m_pszCurr;
  55. *pfRetCode = TRUE;
  56. }
  57. else
  58. {
  59. *pfRetCode = FALSE;
  60. }
  61. }
  62. CMacro::
  63. ~CMacro ( void )
  64. {
  65. delete m_pszBodyBuffer;
  66. Uninstance();
  67. }
  68. void CMacro::
  69. Uninstance ( void )
  70. {
  71. m_ArgList.DeleteList();
  72. m_MacroInstList.DeleteList();
  73. }
  74. BOOL CMacro::
  75. SetBodyPart ( LPSTR pszBodyPart )
  76. {
  77. UINT cch = ::strlen(pszBodyPart);
  78. ASSERT(m_pszCurr + cch + 1 < m_pszBodyBuffer + m_cbMaxBodySize);
  79. if (m_pszCurr + cch + 1 < m_pszBodyBuffer + m_cbMaxBodySize)
  80. {
  81. LPSTR psz;
  82. m_ArgList.Reset();
  83. for (UINT i = 0; NULL != (psz = m_ArgList.Iterate()); i++)
  84. {
  85. if (0 == ::strcmp(pszBodyPart, psz))
  86. {
  87. // this is an argument
  88. m_fArgExistsInBody = TRUE;
  89. *m_pszCurr++ = ARG_ESCAPE_CHAR;
  90. *m_pszCurr++ = ARG_INDEX_BASE + i;
  91. return TRUE;
  92. }
  93. }
  94. // this is not an argument.
  95. ::memcpy(m_pszCurr, pszBodyPart, cch);
  96. m_pszCurr += cch;
  97. *m_pszCurr = '\0';
  98. return TRUE;
  99. }
  100. return FALSE;
  101. }
  102. void CMacro::
  103. EndMacro ( void )
  104. {
  105. // save the count of arguments
  106. m_cFormalArgs = m_ArgList.GetCount();
  107. // calculate the size of the body
  108. m_cbBodySize = m_pszCurr - m_pszBodyBuffer;
  109. // null terminated the body
  110. *m_pszCurr++ = '\0';
  111. // set up the expand buffer
  112. m_pszExpandBuffer = m_pszCurr;
  113. // free the memory
  114. DeleteArgList();
  115. }
  116. BOOL CMacro::
  117. InstantiateMacro ( void )
  118. {
  119. BOOL rc = FALSE; // assume failure
  120. LPSTR pszInstName, pszSrc, pszDst;
  121. UINT i, cch;
  122. CMacroInstance *pInst;
  123. if (! m_fArgExistsInBody)
  124. {
  125. // No need to instantiate because the body does not contain any argument.
  126. // We can take the body as the instance.
  127. rc = TRUE;
  128. goto MyExit;
  129. }
  130. ASSERT(m_ArgList.GetCount() == m_cFormalArgs);
  131. if (m_ArgList.GetCount() != m_cFormalArgs)
  132. {
  133. goto MyExit;
  134. }
  135. pszInstName = CreateInstanceName();
  136. if (NULL == pszInstName)
  137. {
  138. goto MyExit;
  139. }
  140. m_MacroInstList.Reset();
  141. while (NULL != (pInst = m_MacroInstList.Iterate()))
  142. {
  143. if (0 == ::strcmp(pszInstName, pInst->GetName()))
  144. {
  145. // same instance has been instantiated before.
  146. rc = TRUE;
  147. delete pszInstName;
  148. goto MyExit;
  149. }
  150. }
  151. // Let's instantiate a new instance...
  152. pszSrc = m_pszBodyBuffer;
  153. pszDst = m_pszExpandBuffer;
  154. // put in macro name first
  155. ::strcpy(pszDst, pszInstName);
  156. pszDst += ::strlen(pszDst);
  157. // put in macro body now.
  158. while (*pszSrc != '\0')
  159. {
  160. if (*pszSrc == ARG_ESCAPE_CHAR)
  161. {
  162. pszSrc++;
  163. i = *pszSrc++ - ARG_INDEX_BASE;
  164. ASSERT(i < m_ArgList.GetCount());
  165. LPSTR pszArgName = m_ArgList.GetNthItem(i);
  166. cch = ::strlen(pszArgName);
  167. ::memcpy(pszDst, pszArgName, cch);
  168. pszDst += cch;
  169. }
  170. else
  171. {
  172. *pszDst++ = *pszSrc++;
  173. }
  174. }
  175. *pszDst++ = '\n';
  176. *pszDst = '\0';
  177. // create an instance
  178. pInst = new CMacroInstance(&rc,
  179. pszInstName,
  180. pszDst - m_pszExpandBuffer,
  181. m_pszExpandBuffer);
  182. if (NULL != pInst && rc)
  183. {
  184. m_MacroInstList.Append(pInst);
  185. }
  186. MyExit:
  187. // free up temporary argument names
  188. m_ArgList.DeleteList();
  189. return rc;
  190. }
  191. BOOL CMacro::
  192. OutputInstances ( COutput *pOutput )
  193. {
  194. BOOL rc = TRUE;
  195. CMacroInstance *pInst;
  196. if (m_fArgExistsInBody)
  197. {
  198. m_MacroInstList.Reset();
  199. while (NULL != (pInst = m_MacroInstList.Iterate()))
  200. {
  201. rc = pOutput->Write(pInst->GetBuffer(), pInst->GetBufSize());
  202. ASSERT(rc);
  203. }
  204. }
  205. else
  206. {
  207. rc = pOutput->Write(m_pszMacroName, ::strlen(m_pszMacroName));
  208. ASSERT(rc);
  209. rc = pOutput->Writeln(m_pszBodyBuffer, m_cbBodySize);
  210. ASSERT(rc);
  211. }
  212. return rc;
  213. }
  214. LPSTR CMacro::
  215. CreateInstanceName ( void )
  216. {
  217. UINT cch = ::strlen(m_pszMacroName) + 2;
  218. UINT i;
  219. LPSTR psz, pszArgName;
  220. if (m_fArgExistsInBody)
  221. {
  222. ASSERT(m_ArgList.GetCount() == m_cFormalArgs);
  223. m_ArgList.Reset();
  224. while (NULL != (pszArgName = m_ArgList.Iterate()))
  225. {
  226. cch += ::strlen(pszArgName) + 1;
  227. }
  228. }
  229. LPSTR pszInstanceName = new char[cch];
  230. if (NULL != pszInstanceName)
  231. {
  232. psz = pszInstanceName;
  233. ::strcpy(psz, m_pszMacroName);
  234. if (m_fArgExistsInBody)
  235. {
  236. psz += ::strlen(psz);
  237. m_ArgList.Reset();
  238. while (NULL != (pszArgName = m_ArgList.Iterate()))
  239. {
  240. *psz++ = '-';
  241. ::strcpy(psz, pszArgName);
  242. psz += ::strlen(psz);
  243. }
  244. }
  245. }
  246. return pszInstanceName;
  247. }
  248. CMacro * CMacroMgrList::
  249. FindMacro
  250. (
  251. LPSTR pszModuleName,
  252. LPSTR pszMacroName
  253. )
  254. {
  255. CMacroMgr *pMacroMgr = FindMacroMgr(pszModuleName);
  256. return (NULL != pMacroMgr) ? pMacroMgr->FindMacro(pszMacroName) : NULL;
  257. }
  258. CMacroMgr * CMacroMgrList::
  259. FindMacroMgr ( LPSTR pszModuleName )
  260. {
  261. CMacroMgr *pMacroMgr;
  262. Reset();
  263. while (NULL != (pMacroMgr = Iterate()))
  264. {
  265. if (0 == ::strcmp(pszModuleName, pMacroMgr->GetModuleName()))
  266. {
  267. return pMacroMgr;
  268. }
  269. }
  270. return NULL;
  271. }
  272. void CMacroMgrList::
  273. Uninstance ( void )
  274. {
  275. CMacroMgr *pMacroMgr;
  276. Reset();
  277. while (NULL != (pMacroMgr = Iterate()))
  278. {
  279. pMacroMgr->Uninstance();
  280. }
  281. }
  282. CMacroMgr::
  283. CMacroMgr ( void )
  284. :
  285. m_MacroList(16), // default 16 macros
  286. m_pszModuleName(NULL)
  287. {
  288. }
  289. CMacroMgr::
  290. ~CMacroMgr ( void )
  291. {
  292. m_MacroList.DeleteList();
  293. delete m_pszModuleName;
  294. }
  295. BOOL CMacroMgr::
  296. AddModuleName ( LPSTR pszModuleName )
  297. {
  298. // can only be set once
  299. ASSERT(NULL == m_pszModuleName);
  300. m_pszModuleName = ::My_strdup(pszModuleName);
  301. ASSERT(NULL != m_pszModuleName);
  302. return (NULL != m_pszModuleName);
  303. }
  304. CMacro *CMacroMgr::
  305. FindMacro ( LPSTR pszMacroName )
  306. {
  307. CMacro *pMacro;
  308. m_MacroList.Reset();
  309. while (NULL != (pMacro = m_MacroList.Iterate()))
  310. {
  311. if (0 == ::strcmp(pszMacroName, pMacro->GetName()))
  312. {
  313. return pMacro;
  314. }
  315. }
  316. return NULL;
  317. }
  318. BOOL CMacroMgr::
  319. OutputImportedMacros ( COutput *pOutput )
  320. {
  321. BOOL rc = TRUE;
  322. CMacro *pMacro;
  323. rc = pOutput->Write("\n\n", 2);
  324. m_MacroList.Reset();
  325. while (NULL != (pMacro = m_MacroList.Iterate()))
  326. {
  327. if (pMacro->IsImported())
  328. {
  329. rc = pMacro->OutputInstances(pOutput);
  330. if (! rc)
  331. {
  332. ASSERT(0);
  333. return FALSE;
  334. }
  335. }
  336. }
  337. return rc;
  338. }
  339. void CMacroMgr::
  340. Uninstance ( void )
  341. {
  342. CMacro *pMacro;
  343. m_MacroList.Reset();
  344. while (NULL != (pMacro = m_MacroList.Iterate()))
  345. {
  346. pMacro->Uninstance();
  347. }
  348. }
  349. CMacroInstance::
  350. CMacroInstance
  351. (
  352. BOOL *pfRetCode,
  353. LPSTR pszInstanceName,
  354. UINT cbBufSize,
  355. LPSTR pszInstBuf
  356. )
  357. :
  358. m_pszInstanceName(pszInstanceName),
  359. m_cbBufSize(cbBufSize)
  360. {
  361. m_pszInstanceBuffer = new char[m_cbBufSize];
  362. if (NULL != m_pszInstanceBuffer)
  363. {
  364. ::memcpy(m_pszInstanceBuffer, pszInstBuf, m_cbBufSize);
  365. }
  366. *pfRetCode = (NULL != m_pszInstanceName) && (NULL != m_pszInstanceBuffer);
  367. }
  368. CMacroInstance::
  369. ~CMacroInstance ( void )
  370. {
  371. delete m_pszInstanceName;
  372. delete m_pszInstanceBuffer;
  373. }
  374. void CMacroInstList::
  375. DeleteList ( void )
  376. {
  377. CMacroInstance *pInst;
  378. while (NULL != (pInst = Get()))
  379. {
  380. delete pInst;
  381. }
  382. }
  383. void CMacroList::
  384. DeleteList ( void )
  385. {
  386. CMacro *pMacro;
  387. while (NULL != (pMacro = Get()))
  388. {
  389. delete pMacro;
  390. }
  391. }
  392. void CMacroMgrList::
  393. DeleteList ( void )
  394. {
  395. CMacroMgr *pMacroMgr;
  396. while (NULL != (pMacroMgr = Get()))
  397. {
  398. delete pMacroMgr;
  399. }
  400. }
  401. BOOL CNameList::
  402. AddName ( LPSTR pszName )
  403. {
  404. pszName = ::My_strdup(pszName);
  405. if (NULL != pszName)
  406. {
  407. Append(pszName);
  408. return TRUE;
  409. }
  410. return FALSE;
  411. }
  412. LPSTR CNameList::
  413. GetNthItem ( UINT nth )
  414. {
  415. LPSTR psz;
  416. if (nth < GetCount())
  417. {
  418. Reset();
  419. do
  420. {
  421. psz = Iterate();
  422. }
  423. while (nth--);
  424. }
  425. else
  426. {
  427. psz = NULL;
  428. }
  429. return psz;
  430. }
  431. void CNameList::
  432. DeleteList ( void )
  433. {
  434. LPSTR psz;
  435. while (NULL != (psz = Get()))
  436. {
  437. delete psz;
  438. }
  439. }