Leaked source code of windows server 2003
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.

4277 lines
123 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. sortpp.c
  5. Abstract:
  6. This program parses the file winincs.pp and generates a .PPM file
  7. compatible with GENTHNK.
  8. Author:
  9. 08-Jul-1995 JonLe
  10. Revision History:
  11. 27-Nov-1996 BarryBo -- code cleanup and documentation
  12. 20-Mar-1998 mzoran -- Added support for finding COM interfaces
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <assert.h>
  23. #include "gen.h"
  24. // string to put in front of all error messages so that BUILD can find them.
  25. const char *ErrMsgPrefix = "NMAKE : U8604: 'SORTPP' ";
  26. FILE *fpHeaders;
  27. int StatementLineNumber;
  28. char SourceFileName[MAX_PATH+1];
  29. int SourceLineNumber;
  30. int TypeId = 0;
  31. void DumpLexerOutput(int FirstToken);
  32. //
  33. // packing size as specified by /Zp option to the CL command
  34. //
  35. #define DEFAULTPACKINGSIZE 8
  36. DWORD dwPackingCurrent = DEFAULTPACKINGSIZE;
  37. typedef struct _packholder {
  38. struct _packholder *ppackholderNext;
  39. DWORD dwPacking;
  40. char sIdentifier[1];
  41. } PACKHOLDER;
  42. PACKHOLDER *ppackholderHead = NULL;
  43. struct TypeInfoListElement {
  44. struct TypeInfoListElement *pNext;
  45. TYPESINFO *pTypeInfo;
  46. };
  47. typedef struct TypeInfoListElement *PTYPEINFOELEMENT;
  48. PKNOWNTYPES NIL; // for red-black trees
  49. PRBTREE FuncsList;
  50. PRBTREE StructsList;
  51. PRBTREE TypeDefsList;
  52. RBTREE _VarsList;
  53. PRBTREE VarsList = &_VarsList; // Used to track global variable declarations.
  54. // Should not appear in the PPM file
  55. char Headers[MAX_PATH+1];
  56. char ppmName[MAX_PATH+1];
  57. HANDLE hCvmHeap;
  58. ULONG uBaseAddress = 0x30000000;
  59. ULONG uReserveSize = 0x01800000;
  60. BOOL bLine = FALSE;
  61. char szThis[] = "This";
  62. DWORD dwScopeLevel = 0;
  63. void ExtractDerivedTypes(void);
  64. BOOL LexNextStatement(void);
  65. BOOL ParseFuncTypes(PTYPESINFO pTypesInfo, BOOL fDllImport);
  66. BOOL ParseStructTypes(PTYPESINFO pTypesInfo);
  67. BOOL ParseTypeDefs(PTYPESINFO pTypesInfo);
  68. BOOL ParseVariables(VOID);
  69. BOOL ParseGuid(GUID *pGuid);
  70. BOOL AddDefaultDerivedTypes(void);
  71. PKNOWNTYPES AddNewType(PTYPESINFO pTypesInfo, PRBTREE pTypesList);
  72. BOOL CopyStructMembers(PTYPESINFO pTypesInfo, BOOL bUnion, PKNOWNTYPES pBaseType);
  73. BOOL CopyEnumMembers(PTYPESINFO);
  74. int CreatePseudoName(char *pDst, char *pSrc);
  75. BOOL GetArrayIndex(DWORD *pdw);
  76. LONGLONG expr(void);
  77. LONGLONG expr_a1(void);
  78. LONGLONG expr_a(void);
  79. LONGLONG expr_b(void);
  80. LONGLONG expr_c(void);
  81. void CheckUpdateTypedefSizes(PTYPESINFO ptypesinfo);
  82. PVOID SortppAllocCvm(ULONG Size);
  83. BOOL WritePpmFile(char *PpmName);
  84. void BumpStructUnionSize(DWORD *pdwSize, DWORD dwElemSize, BOOL bUnion);
  85. BOOL GetExistingType(PTYPESINFO pTypesInfo, PBOOL pbFnPtr, PKNOWNTYPES *ppKnownTypes);
  86. BOOL PrepareMappedMemory(void);
  87. DWORD PackPaddingSize(DWORD dwCurrentSize, DWORD dwBase);
  88. void PackPush(char *sIdentifier);
  89. DWORD PackPop(char *sIdentifier);
  90. BOOL ConsumeDeclSpecOpt(BOOL IsFunc, BOOL bInitReturns, BOOL *pIsDllImport, BOOL *pIsGuidDefined, GUID *pGuid);
  91. TOKENTYPE ConsumeDirectionOpt(void);
  92. TOKENTYPE ConsumeConstVolatileOpt(void);
  93. PTYPEINFOELEMENT TypeInfoElementAllocateLink(PTYPEINFOELEMENT *ppHead, PTYPEINFOELEMENT pThis, TYPESINFO *pType);
  94. VOID UpdateGuids(VOID);
  95. BOOL AddVariable(char *Name, GUID * pGuid);
  96. VOID GenerateProxy(char *pName, PTYPESINFO pTypesInfo);
  97. VOID FreeTypeInfoList(PTYPEINFOELEMENT pThis);
  98. PMEMBERINFO CatMeminfo(BUFALLOCINFO *pBufallocinfo, PMEMBERINFO pHead, PMEMBERINFO pTail, DWORD dwOffset, BOOL bStatus);
  99. BOOL ConsumeExternC(void);
  100. //
  101. // PPC compiler is screwing up the Initializa list head macro !
  102. //
  103. #if defined (_PPC_)
  104. #undef InitializeListHead
  105. #define InitializeListHead(ListHead) ( (ListHead)->Flink = (ListHead), \
  106. (ListHead)->Blink = (ListHead) \
  107. )
  108. #endif
  109. _inline void
  110. PackModify(
  111. DWORD dw
  112. )
  113. {
  114. dwPackingCurrent = dw;
  115. DbgPrintf("new packing is %x\n", dw);
  116. }
  117. _inline DWORD
  118. PackCurrentPacking(
  119. void
  120. )
  121. {
  122. return dwPackingCurrent;
  123. }
  124. DWORD PackPaddingSize(DWORD dwCurrentSize, DWORD dwBase)
  125. {
  126. DWORD dw;
  127. if (dwCurrentSize == 0) {
  128. return 0; // no padding for first member
  129. }
  130. if (dwBase == 0) {
  131. dwBase = SIZEOFPOINTER;
  132. } // if no base size yet then must be a ptr
  133. // base is min(size, packing)
  134. if (dwBase > PackCurrentPacking()) {
  135. dwBase = PackCurrentPacking();
  136. }
  137. // figure out padding
  138. return (dwBase - (dwCurrentSize % dwBase)) % dwBase;
  139. }
  140. _inline DWORD PackPackingSize(DWORD dwCurrentSize, DWORD dwSize,
  141. DWORD dwBase)
  142. {
  143. // round up to nearest dwBase
  144. return PackPaddingSize(dwCurrentSize, dwBase) + dwSize;
  145. }
  146. /* main
  147. *
  148. * standard win32 base windows entry point
  149. * returns 0 for clean exit, otherwise nonzero for error
  150. *
  151. *
  152. * ExitCode:
  153. * 0 - Clean exit with no Errors
  154. * nonzero - error ocurred
  155. *
  156. */
  157. int __cdecl main(int argc, char **argv)
  158. {
  159. int i;
  160. char *pHeaders = NULL;
  161. char *pch;
  162. DWORD LenHeaders=0;
  163. SetConsoleCtrlHandler(ConsoleControlHandler, TRUE);
  164. try {
  165. /*
  166. * Get cmd line args.
  167. */
  168. i = 0;
  169. while (++i < argc) {
  170. pch = argv[i];
  171. if (*pch == '-' || *pch == '/') {
  172. pch++;
  173. switch (toupper(*pch)) {
  174. case 'D': // debug forces extra check
  175. bDebug = TRUE;
  176. setvbuf(stderr, NULL, _IONBF, 0);
  177. break;
  178. case 'L':
  179. bLine = TRUE;
  180. break;
  181. case 'M': // ppm output filename
  182. strcpy(ppmName, ++pch);
  183. DeleteFile(ppmName);
  184. break;
  185. case 'B': // gBaseAddress
  186. pch++;
  187. uBaseAddress = atoi(pch);
  188. break;
  189. case 'R': // Reserve size
  190. pch++;
  191. uReserveSize = atoi(pch);
  192. break;
  193. case '?': // usage
  194. ExitErrMsg(FALSE,
  195. "sortpp -d -l -w -m<ppm file> -b<Base addr> -r<reserved> <pp file>\n");
  196. default:
  197. ExitErrMsg(FALSE, "Unrecognized option %s\n", pch);
  198. }
  199. } else if (*pch) {
  200. strcpy(Headers, pch);
  201. }
  202. }
  203. if (!*Headers) {
  204. ExitErrMsg(FALSE, "no Headers file name\n");
  205. }
  206. if (!*ppmName) {
  207. ExitErrMsg(FALSE, "no -m<PPM filename>\n");
  208. }
  209. DbgPrintf("%s -> %s\n", Headers, ppmName);
  210. if (!PrepareMappedMemory()) {
  211. ExitErrMsg(FALSE, "Problem in PrepareMappedMemory %s, gle = %d\n",
  212. Headers, GetLastError());
  213. }
  214. RBInitTree(FuncsList);
  215. RBInitTree(StructsList);
  216. RBInitTree(TypeDefsList);
  217. RBInitTree(VarsList); //not in the PPM file
  218. fpHeaders = fopen(Headers, "r");
  219. if (fpHeaders == NULL) {
  220. ExitErrMsg(FALSE, "Headers open '%s' errno=%d\n", Headers, errno);
  221. }
  222. if (!AddDefaultDerivedTypes()) {
  223. ExitErrMsg(TRUE, "AddDefaultDerivedTypes failed\n");
  224. }
  225. // pull out the different types: structs, typedefs function prototypes
  226. ExtractDerivedTypes();
  227. // Attempt to update guids for structs that don't have them
  228. UpdateGuids();
  229. if (!WritePpmFile(ppmName)) {
  230. ExitErrMsg(FALSE, "Problem in WritePpmFile gle = %d\n", GetLastError());
  231. }
  232. } except(EXCEPTION_EXECUTE_HANDLER) {
  233. ExitErrMsg(FALSE,
  234. "sortpp: ExceptionCode=%x\n",
  235. GetExceptionCode()
  236. );
  237. }
  238. DeleteAllocCvmHeap(hCvmHeap);
  239. return 0;
  240. }
  241. BOOL
  242. AddDefaultDerivedTypes(
  243. void
  244. )
  245. /*++
  246. Routine Description:
  247. Add signed, unsigned to TypeDefsList. Treated as derived types
  248. based on int.
  249. Arguments:
  250. None.
  251. Return Value:
  252. TRUE on success, FALSE on failure (probably out-of-memory)
  253. --*/
  254. {
  255. TYPESINFO TypesInfo;
  256. PFUNCINFO funcinfo;
  257. memset(&TypesInfo, 0, sizeof(TYPESINFO));
  258. strcpy(TypesInfo.BasicType,szINT);
  259. strcpy(TypesInfo.BaseName,szINT);
  260. strcpy(TypesInfo.TypeName,szINT);
  261. TypesInfo.Size = sizeof(int);
  262. TypesInfo.iPackSize = sizeof(int);
  263. TypesInfo.Flags = BTI_NOTDERIVED;
  264. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  265. return FALSE;
  266. }
  267. strcpy(TypesInfo.TypeName,"unsigned int");
  268. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED;
  269. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  270. return FALSE;
  271. }
  272. strcpy(TypesInfo.TypeName,"short int");
  273. TypesInfo.Size = sizeof(short int);
  274. TypesInfo.iPackSize = sizeof(short int);
  275. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED;
  276. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  277. return FALSE;
  278. }
  279. strcpy(TypesInfo.TypeName,"unsigned short int");
  280. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED;
  281. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  282. return FALSE;
  283. }
  284. strcpy(TypesInfo.TypeName,"long int");
  285. TypesInfo.Size = sizeof(long int);
  286. TypesInfo.iPackSize = sizeof(long int);
  287. TypesInfo.Flags = BTI_NOTDERIVED;
  288. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  289. return FALSE;
  290. }
  291. strcpy(TypesInfo.TypeName,"unsigned long int");
  292. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED;
  293. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  294. return FALSE;
  295. }
  296. strcpy(TypesInfo.BasicType,szCHAR);
  297. strcpy(TypesInfo.BaseName,szCHAR);
  298. strcpy(TypesInfo.TypeName,szCHAR);
  299. TypesInfo.Size = sizeof(char);
  300. TypesInfo.iPackSize = sizeof(char);
  301. TypesInfo.Flags = BTI_NOTDERIVED;
  302. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  303. return FALSE;
  304. }
  305. strcpy(TypesInfo.TypeName,szUNSIGNEDCHAR);
  306. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED;
  307. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  308. return FALSE;
  309. }
  310. strcpy(TypesInfo.BasicType,szINT64);
  311. strcpy(TypesInfo.BaseName,szINT64);
  312. strcpy(TypesInfo.TypeName,szINT64);
  313. TypesInfo.Size = sizeof(__int64);
  314. TypesInfo.iPackSize = sizeof(__int64);
  315. TypesInfo.Flags = BTI_NOTDERIVED | BTI_INT64DEP | BTI_POINTERDEP;
  316. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  317. return FALSE;
  318. }
  319. strcpy(TypesInfo.TypeName,"unsigned _int64");
  320. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED | BTI_INT64DEP | BTI_POINTERDEP;
  321. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  322. return FALSE;
  323. }
  324. strcpy(TypesInfo.BasicType,sz_INT64);
  325. strcpy(TypesInfo.BaseName,sz_INT64);
  326. strcpy(TypesInfo.TypeName,sz_INT64);
  327. TypesInfo.Flags = BTI_NOTDERIVED | BTI_INT64DEP | BTI_POINTERDEP;
  328. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  329. return FALSE;
  330. }
  331. strcpy(TypesInfo.TypeName,"unsigned __int64");
  332. TypesInfo.Flags = BTI_NOTDERIVED | BTI_UNSIGNED | BTI_INT64DEP | BTI_POINTERDEP;
  333. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  334. return FALSE;
  335. }
  336. strcpy(TypesInfo.BasicType,szDOUBLE);
  337. strcpy(TypesInfo.BaseName,szDOUBLE);
  338. strcpy(TypesInfo.TypeName,szDOUBLE);
  339. TypesInfo.Size = sizeof(double);
  340. TypesInfo.iPackSize = sizeof(double);
  341. TypesInfo.Flags = BTI_NOTDERIVED;
  342. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  343. return FALSE;
  344. }
  345. strcpy(TypesInfo.BasicType,szFLOAT);
  346. strcpy(TypesInfo.BaseName,szFLOAT);
  347. strcpy(TypesInfo.TypeName,szFLOAT);
  348. TypesInfo.Size = sizeof(float);
  349. TypesInfo.iPackSize = sizeof(float);
  350. TypesInfo.Flags = BTI_NOTDERIVED;
  351. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  352. return FALSE;
  353. }
  354. strcpy(TypesInfo.BasicType,szVOID);
  355. strcpy(TypesInfo.BaseName,szVOID);
  356. strcpy(TypesInfo.TypeName,szVOID);
  357. TypesInfo.Size = 0;
  358. TypesInfo.iPackSize = 0;
  359. TypesInfo.Flags = BTI_NOTDERIVED;
  360. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  361. return FALSE;
  362. }
  363. strcpy(TypesInfo.BasicType,szGUID);
  364. strcpy(TypesInfo.BaseName,szGUID);
  365. strcpy(TypesInfo.TypeName,szGUID);
  366. TypesInfo.Size = 16;
  367. TypesInfo.iPackSize = 16;
  368. TypesInfo.Flags = BTI_NOTDERIVED;
  369. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  370. return FALSE;
  371. }
  372. strcpy(TypesInfo.BasicType,szFUNC);
  373. strcpy(TypesInfo.BaseName,szFUNC);
  374. strcpy(TypesInfo.TypeName,szFUNC);
  375. TypesInfo.Flags = BTI_CONTAINSFUNCPTR | BTI_NOTDERIVED;
  376. TypesInfo.Size = 4;
  377. TypesInfo.iPackSize = 4;
  378. TypesInfo.dwMemberSize = sizeof(FUNCINFO)+strlen(szVOID)+1;
  379. TypesInfo.TypeKind = TypeKindFunc;
  380. funcinfo = (PFUNCINFO)TypesInfo.Members;
  381. TypesInfo.pfuncinfo = funcinfo;
  382. funcinfo->sType = TypesInfo.Members + sizeof(FUNCINFO);
  383. strcpy(funcinfo->sType, szVOID);
  384. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  385. return FALSE;
  386. }
  387. TypesInfo.dwMemberSize = 0;
  388. TypesInfo.Flags = BTI_NOTDERIVED;
  389. TypesInfo.TypeKind = TypeKindEmpty;
  390. TypesInfo.pfuncinfo = NULL;
  391. memset(TypesInfo.Members, 0, sizeof(TypesInfo.Members));
  392. strcpy(TypesInfo.BasicType,szVARGS);
  393. strcpy(TypesInfo.BaseName,szVARGS);
  394. strcpy(TypesInfo.TypeName,szVARGS);
  395. TypesInfo.Size = 0; // varargs has size of 0
  396. TypesInfo.iPackSize = 0;
  397. TypesInfo.Flags = BTI_NOTDERIVED;
  398. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  399. return FALSE;
  400. }
  401. // Generic pointer type. Not generated by sortpp, but used by genthnk
  402. strcpy(TypesInfo.BasicType, "*");
  403. strcpy(TypesInfo.BaseName, "*");
  404. strcpy(TypesInfo.TypeName, "*");
  405. TypesInfo.IndLevel = 1;
  406. TypesInfo.Flags = BTI_NOTDERIVED;
  407. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  408. return FALSE;
  409. }
  410. // Generic struct type. Not generated by sortpp, but used by genthnk
  411. strcpy(TypesInfo.BasicType, "struct");
  412. strcpy(TypesInfo.BaseName, "struct");
  413. strcpy(TypesInfo.TypeName, "struct");
  414. TypesInfo.IndLevel = 0;
  415. TypesInfo.Flags = BTI_NOTDERIVED;
  416. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  417. return FALSE;
  418. }
  419. // Generic union type. Not generated by sortpp, but used by genthnk
  420. strcpy(TypesInfo.BasicType, "union");
  421. strcpy(TypesInfo.BaseName, "union");
  422. strcpy(TypesInfo.TypeName, "union");
  423. TypesInfo.IndLevel = 0;
  424. TypesInfo.Flags = BTI_NOTDERIVED;
  425. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  426. return FALSE;
  427. }
  428. // Default type that matches all types. Not generated by sortpp, but used by genthnk
  429. strcpy(TypesInfo.BasicType, "default");
  430. strcpy(TypesInfo.BaseName, "default");
  431. strcpy(TypesInfo.TypeName, "default");
  432. TypesInfo.IndLevel = 0;
  433. TypesInfo.Flags = BTI_NOTDERIVED;
  434. if (!AddToTypesList(TypeDefsList, &TypesInfo)) {
  435. return FALSE;
  436. }
  437. return TRUE;
  438. }
  439. BOOL
  440. ConsumeExternC(
  441. void
  442. )
  443. {
  444. /*++
  445. Routine Description:
  446. Consumes an extern or an extern "C".
  447. Arguments:
  448. None.
  449. Return Value:
  450. TRUE - extern or extern "C" was consumed.
  451. --*/
  452. PTOKEN Token;
  453. Token = CurrentToken();
  454. if (Token->TokenType == TK_EXTERN) {
  455. ConsumeToken();
  456. Token = CurrentToken();
  457. if (Token->TokenType == TK_STRING &&
  458. strcmp(Token->Name, "C") == 0)
  459. ConsumeToken();
  460. return TRUE;
  461. }
  462. return FALSE;
  463. }
  464. void
  465. ExtractDerivedTypes(
  466. void
  467. )
  468. /*++
  469. Routine Description:
  470. Removes derived type definitions from headers, building the
  471. TypesDef, Structs, and Funcs lists.
  472. Arguments:
  473. None.
  474. Return Value:
  475. None.
  476. --*/
  477. {
  478. TYPESINFO TypesInfo;
  479. PRBTREE pListHead;
  480. BOOL fDllImport;
  481. //
  482. // Lex in entire C-language statements, then parse them. Stops at EOF.
  483. //
  484. while (LexNextStatement()) {
  485. int OldTokenIndex;
  486. int c;
  487. if (bDebug) {
  488. DumpLexerOutput(0);
  489. }
  490. if (bLine) {
  491. for(c=80; c > 0; c--)
  492. fputc('\b', stderr);
  493. c = fprintf(stderr, "Status: %s(%d)", SourceFileName, StatementLineNumber);
  494. for(; c < 78; c++)
  495. fputc(' ', stderr);
  496. fflush(stderr);
  497. }
  498. pListHead = NULL;
  499. assert(dwScopeLevel == 0);
  500. if (CurrentToken()->TokenType == TK_EOS) {
  501. //ddraw.h has an extra ; at the end of an extern "C" block
  502. continue;
  503. }
  504. ConsumeExternC();
  505. ConsumeDeclSpecOpt(TRUE, TRUE, &fDllImport, NULL, NULL);
  506. ConsumeExternC();
  507. OldTokenIndex = CurrentTokenIndex;
  508. //
  509. // Try to parse as a TypeDef.
  510. //
  511. if (ParseTypeDefs(&TypesInfo)) {
  512. //
  513. // Got a typedef
  514. //
  515. if (CurrentToken()->TokenType == TK_EOS) {
  516. pListHead = TypeDefsList;
  517. goto DoAddNewType;
  518. }
  519. }
  520. //
  521. // Failed to parse as TypeDef. Try to parse as a struct/union/enum
  522. //
  523. CurrentTokenIndex = OldTokenIndex;
  524. if (ParseStructTypes(&TypesInfo)) {
  525. //
  526. // got a struct definition
  527. //
  528. if (CurrentToken()->TokenType == TK_EOS) {
  529. pListHead = StructsList;
  530. goto DoAddNewType;
  531. }
  532. }
  533. //
  534. // Failed to parse as struct/union/enum. Try to parse as function
  535. //
  536. CurrentTokenIndex = OldTokenIndex;
  537. if (ParseFuncTypes(&TypesInfo, fDllImport)) {
  538. //
  539. // got a function prototype
  540. //
  541. if (CurrentToken()->TokenType == TK_EOS && !TypesInfo.IndLevel) {
  542. pListHead = FuncsList;
  543. goto DoAddNewType;
  544. }
  545. }
  546. CurrentTokenIndex = OldTokenIndex;
  547. if (ParseVariables()) continue;
  548. CurrentTokenIndex = OldTokenIndex;
  549. DoAddNewType:
  550. if (pListHead && !AddNewType(&TypesInfo, pListHead)) {
  551. ErrMsg("AddNewType fail\n");
  552. }
  553. if (CurrentToken()->TokenType != TK_EOS && bDebug) {
  554. fprintf(stderr, "Warning: Rejected %s(%d)\n", SourceFileName, StatementLineNumber);
  555. //
  556. // Use the 8k buffer in TypesInfo.Members to unlex the source stmt
  557. //
  558. UnlexToText(TypesInfo.Members,
  559. sizeof(TypesInfo.Members),
  560. 0,
  561. MAX_TOKENS_IN_STATEMENT);
  562. fprintf(stderr, "\t%s;\n", TypesInfo.Members);
  563. }
  564. }
  565. }
  566. PKNOWNTYPES
  567. AddNewType(
  568. PTYPESINFO pTypesInfo,
  569. PRBTREE pTypesList
  570. )
  571. /*++
  572. Routine Description:
  573. Adds a new type to a types list.
  574. Arguments:
  575. pTypesInfo -- type to add
  576. pTypesList -- list to add the type to
  577. Return Value:
  578. Returns a pointer to the KNOWNTYPES for the new type on success,
  579. NULL for error.
  580. --*/
  581. {
  582. PKNOWNTYPES pkt;
  583. PKNOWNTYPES pKnownTypes = NULL;
  584. PDEFBASICTYPES pdbt;
  585. ULONG Flags = 0;
  586. BOOL bRet = FALSE;
  587. if (((pTypesList == TypeDefsList) || (pTypesList == StructsList)) &&
  588. (((pTypesInfo->Size == 0) || (pTypesInfo->iPackSize == 0)) &&
  589. (*pTypesInfo->Members != 0))) {
  590. DbgPrintf("Added type with invalid size %s %s %s %d %d\n",
  591. pTypesInfo->BasicType,
  592. pTypesInfo->BaseName,
  593. pTypesInfo->TypeName,
  594. pTypesInfo->Size,
  595. pTypesInfo->iPackSize);
  596. }
  597. pTypesInfo->TypeId = TypeId++;
  598. pTypesInfo->LineNumber = SourceLineNumber;
  599. pTypesInfo->dwScopeLevel = dwScopeLevel;
  600. pTypesInfo->dwCurrentPacking = PackCurrentPacking();
  601. if (strlen(SourceFileName) > sizeof(pTypesInfo->FileName) - 1)
  602. ExitErrMsg(FALSE, "Source file name is too large.\n");
  603. strcpy(pTypesInfo->FileName, SourceFileName);
  604. if (IsDefinedPointerDependent(pTypesInfo->TypeName))
  605. pTypesInfo->Flags |= BTI_POINTERDEP;
  606. //
  607. // Loop up the type and see if it is already in the list
  608. //
  609. pkt = GetNameFromTypesList(pTypesList, pTypesInfo->TypeName);
  610. if (pkt) {
  611. //
  612. // Uncomment the next line and comment the following line to change the
  613. // behavior of this function. By doing this you will allow functions to be
  614. // redefined in the following case: First a function that has no arguments
  615. // is encountered and entered in the list. Later the same function is
  616. // encountered with arguments and the new definition for it would override
  617. // the old.
  618. // if ((pTypesList == StructsList) || (pTypesList == FuncsList)) {
  619. if (pTypesList == StructsList) {
  620. if (pTypesInfo->dwMemberSize == 0) {
  621. //
  622. // Since the struct has already been defined lets grab its
  623. // relevant size information.
  624. //
  625. pTypesInfo->IndLevel = pkt->IndLevel;
  626. pTypesInfo->Size = pkt->Size;
  627. pTypesInfo->iPackSize = pkt->iPackSize;
  628. pTypesInfo->TypeId = pkt->TypeId;
  629. return pkt;
  630. }
  631. if (! pkt->pmeminfo) {
  632. //
  633. // Find any previously defined typedefs that are based upon this
  634. // struct and fix their size.
  635. CheckUpdateTypedefSizes(pTypesInfo);
  636. ReplaceInTypesList(pkt, pTypesInfo);
  637. return pkt;
  638. }
  639. }
  640. else if (pkt->Flags & BTI_DISCARDABLE) {
  641. ReplaceInTypesList(pkt, pTypesInfo);
  642. return pkt;
  643. }
  644. //
  645. // else if it already exists, assume is the same
  646. //
  647. DbgPrintf("typedef: %s previously defined\n", pTypesInfo->TypeName);
  648. return pkt;
  649. }
  650. //
  651. // Type is not already listed. Look up its basic type
  652. //
  653. pdbt = GetDefBasicType(pTypesInfo->BasicType);
  654. if (pdbt) {
  655. Flags = 0;
  656. } else {
  657. pkt = GetNameFromTypesList(pTypesList, pTypesInfo->BasicType);
  658. if (pkt) {
  659. Flags = pkt->Flags;
  660. pdbt = GetDefBasicType(pkt->BasicType);
  661. if (!pdbt) {
  662. ErrMsg("types Table corrupt %s\n", pkt->TypeName);
  663. }
  664. } else {
  665. ErrMsg("ant: unknown Basic Type %s\n", pTypesInfo->BasicType);
  666. goto ErrorExit;
  667. }
  668. }
  669. pTypesInfo->Flags |= Flags;
  670. strcpy(pTypesInfo->BasicType, pdbt->BasicType);
  671. pKnownTypes = AddToTypesList(pTypesList, pTypesInfo);
  672. if (pKnownTypes == NULL)
  673. goto ErrorExit;
  674. if (bDebug)
  675. DumpTypesInfo(pTypesInfo, stdout);
  676. return pKnownTypes;
  677. ErrorExit:
  678. if (bDebug) {
  679. DumpTypesInfo(pTypesInfo, stdout);
  680. }
  681. DumpTypesInfo(pTypesInfo, stderr);
  682. return NULL;
  683. }
  684. void
  685. CheckUpdateTypedefSizes(
  686. PTYPESINFO ptypesinfo
  687. )
  688. /*++
  689. Routine Description:
  690. We are about to replace an empty struct definition with one that has
  691. members and thus a size. We need to look through the typedefs list and
  692. see if any that have a size of 0 are defined from this new struct and if
  693. so then fix its size and packing size.
  694. Arguments:
  695. ptypesinfo -- struc definition with members
  696. Return Value:
  697. None.
  698. --*/
  699. {
  700. PKNOWNTYPES pknwntyp, pkt;
  701. pknwntyp = TypeDefsList->pLastNodeInserted;
  702. while (pknwntyp) {
  703. if (pknwntyp->Size == 0) {
  704. pkt = GetBasicType(pknwntyp->TypeName, TypeDefsList, StructsList);
  705. if (pkt && ( ! strcmp(pkt->BasicType, szSTRUCT)) &&
  706. ( ! strcmp(pkt->TypeName, ptypesinfo->TypeName))) {
  707. pknwntyp->Size = ptypesinfo->Size;
  708. pknwntyp->iPackSize = ptypesinfo->iPackSize;
  709. pknwntyp->Flags |= (ptypesinfo->Flags & BTI_CONTAINSFUNCPTR);
  710. }
  711. }
  712. pknwntyp = pknwntyp->Next;
  713. }
  714. }
  715. BOOL
  716. GetExistingType(
  717. PTYPESINFO pTypesInfo,
  718. PBOOL pbFnPtr,
  719. PKNOWNTYPES *ppKnownTypes
  720. )
  721. /*++
  722. Routine Description:
  723. Gets an existing type from the lexer stream and returns the type
  724. information for it.
  725. Arguments:
  726. pSrc -- IN ptr to start of typename to look up
  727. pTypesInfo -- Information of
  728. pbFnPtr -- [OPTIONAL] OUT TRUE if the type is a pointer to a function
  729. ppKnownTypes-- [OPTIONAL] OUT KnownType infomation for this type if not a function pointer.
  730. Return Value:
  731. FALSE if the name is not an existing type, or TRUE if the name is an
  732. existing type (CurrentToken ends up pointing at the token following the
  733. type).
  734. --*/
  735. {
  736. PKNOWNTYPES pKnownType;
  737. int OldCurrentTokenIndex = CurrentTokenIndex;
  738. if (bDebug) {
  739. fputs("GetExisting type called with the following lexer state:\n", stderr);
  740. DumpLexerOutput(CurrentTokenIndex);
  741. }
  742. memset(pTypesInfo, 0, sizeof(TYPESINFO));
  743. if (pbFnPtr) {
  744. *pbFnPtr = FALSE;
  745. }
  746. if (ParseStructTypes(pTypesInfo)) {
  747. if ((pKnownType = AddNewType(pTypesInfo, StructsList)) != NULL) {
  748. if (ppKnownTypes != NULL) *ppKnownTypes = pKnownType;
  749. return TRUE;
  750. } else {
  751. if (ppKnownTypes != NULL) *ppKnownTypes = NULL;
  752. return FALSE;
  753. }
  754. }
  755. CurrentTokenIndex = OldCurrentTokenIndex;
  756. if (pbFnPtr && ParseFuncTypes(pTypesInfo, FALSE)) {
  757. if (ppKnownTypes != NULL) *ppKnownTypes = NULL;
  758. *pbFnPtr = TRUE;
  759. return TRUE;
  760. }
  761. CurrentTokenIndex = OldCurrentTokenIndex;
  762. if (ParseTypes(TypeDefsList, pTypesInfo, &pKnownType)) {
  763. if (ppKnownTypes != NULL) *ppKnownTypes = pKnownType;
  764. return TRUE;
  765. }
  766. CurrentTokenIndex = OldCurrentTokenIndex;
  767. if (ParseTypes(StructsList, pTypesInfo, &pKnownType)) {
  768. if (ppKnownTypes != NULL) *ppKnownTypes = pKnownType;
  769. return TRUE;
  770. }
  771. return FALSE;
  772. }
  773. BOOL
  774. ParseTypeDefs(
  775. PTYPESINFO pTypesInfo
  776. )
  777. /*++
  778. Routine Description:
  779. Parses a C-language statement if it is a 'typedef'. Accepted syntaxes are:
  780. typedef <mod> type <indir> NewName<[]> <, <indir> NewName<[]>>
  781. typedef <mod> struct|enum|union <name> <indir> NewName <, <indir> NewName>
  782. typedef <mod> rtype <indir>(<modifiers * NewName ) ( <arg List>)
  783. (Note that we don't deal with extraneous parens very well)
  784. Arguments:
  785. pTypesInfo -- OUT ptr to info about the type
  786. Return Value:
  787. TRUE if the statement is a typedef
  788. FALSE if the statement is not a typedef or some kind of error
  789. --*/
  790. {
  791. int IndLevel;
  792. BOOL bFnPtr = FALSE;
  793. TYPESINFO TypesInfo;
  794. DWORD dwSize;
  795. PKNOWNTYPES pKnownTypes = NULL;
  796. int i;
  797. int Flags;
  798. memset(pTypesInfo, 0, sizeof(TYPESINFO));
  799. if (CurrentToken()->TokenType == TK_DECLSPEC) {
  800. ConsumeDeclSpecOpt(FALSE, FALSE, NULL, NULL, NULL);
  801. }
  802. if (CurrentToken()->TokenType != TK_TYPEDEF) {
  803. //
  804. // Line doesn't start with 'typedef'
  805. //
  806. return FALSE;
  807. }
  808. ConsumeToken();
  809. if (CurrentToken()->TokenType == TK_STAR ||
  810. CurrentToken()->TokenType == TK_BITWISE_AND) {
  811. //
  812. // We have something like: 'typedef *foo;'. This happens if a
  813. // .IDL file has a bogus typedef. MIDL just omits the typename
  814. // if it isn't recognized. Fake up a TypesInfo for 'int'.
  815. //
  816. ConsumeToken();
  817. bFnPtr = FALSE;
  818. memset(&TypesInfo, 0, sizeof(TypesInfo));
  819. strcpy(TypesInfo.BasicType,szINT);
  820. strcpy(TypesInfo.BaseName,szINT);
  821. strcpy(TypesInfo.TypeName,szINT);
  822. TypesInfo.Size = sizeof(int);
  823. TypesInfo.iPackSize = sizeof(int);
  824. } else {
  825. if (IsTokenSeparator() && CurrentToken()->TokenType != TK_LPAREN) {
  826. //
  827. // Text after 'typedef' doesn't start with anything plausible.
  828. //
  829. return FALSE;
  830. }
  831. ConsumeDeclSpecOpt(FALSE, FALSE, NULL, NULL, NULL);
  832. ConsumeConstVolatileOpt();
  833. if (!GetExistingType(&TypesInfo, &bFnPtr, &pKnownTypes)) {
  834. return FALSE;
  835. }
  836. }
  837. //
  838. // We now know the type. Parse new type names derived from that type.
  839. //
  840. pTypesInfo->IndLevel = TypesInfo.IndLevel;
  841. pTypesInfo->Flags |= (TypesInfo.Flags & BTI_CONTAINSFUNCPTR);
  842. pTypesInfo->Flags |= (TypesInfo.Flags & BTI_POINTERDEP);
  843. pTypesInfo->Flags |= (TypesInfo.Flags & BTI_UNSIGNED);
  844. pTypesInfo->pTypedefBase = pKnownTypes;
  845. strcpy(pTypesInfo->BasicType, TypesInfo.BasicType);
  846. strcpy(pTypesInfo->TypeName, TypesInfo.TypeName);
  847. if (bFnPtr) {
  848. //
  849. // The type is a pointer to a function
  850. //
  851. pTypesInfo->Flags |= BTI_CONTAINSFUNCPTR;
  852. strcpy(pTypesInfo->BaseName, TypesInfo.BaseName);
  853. strcpy(pTypesInfo->FuncRet, TypesInfo.FuncRet);
  854. strcpy(pTypesInfo->FuncMod, TypesInfo.FuncMod);
  855. pTypesInfo->Size = SIZEOFPOINTER;
  856. pTypesInfo->iPackSize = SIZEOFPOINTER;
  857. pTypesInfo->dwMemberSize = TypesInfo.dwMemberSize;
  858. pTypesInfo->TypeKind = TypesInfo.TypeKind;
  859. memcpy(pTypesInfo->Members, TypesInfo.Members, sizeof(TypesInfo.Members));
  860. pTypesInfo->pfuncinfo = RelocateTypesInfo(pTypesInfo->Members,
  861. &TypesInfo);
  862. return TRUE;
  863. }
  864. if (CurrentToken()->TokenType == TK_EOS) {
  865. return FALSE;
  866. }
  867. strcpy(pTypesInfo->BaseName, TypesInfo.TypeName);
  868. *pTypesInfo->TypeName = '\0';
  869. // don't handle extraneous parens.
  870. i = CurrentTokenIndex;
  871. while (CurrentToken()->TokenType != TK_EOS) {
  872. if (CurrentToken()->TokenType == TK_LPAREN) {
  873. return FALSE;
  874. }
  875. ConsumeToken();
  876. }
  877. CurrentTokenIndex = i;
  878. IndLevel = pTypesInfo->IndLevel;
  879. Flags = pTypesInfo->Flags;
  880. for (;;) {
  881. pTypesInfo->IndLevel = IndLevel;
  882. pTypesInfo->iPackSize = TypesInfo.iPackSize;
  883. pTypesInfo->Flags = Flags;
  884. dwSize = TypesInfo.Size;
  885. //
  886. // Skip 'const' keyword, if present.
  887. //
  888. if (CurrentToken()->TokenType == TK_CONST) {
  889. ConsumeToken();
  890. }
  891. //
  892. // Handle pointers to the base type
  893. //
  894. if (IsTokenSeparator() &&
  895. CurrentToken()->TokenType != TK_STAR &&
  896. CurrentToken()->TokenType != TK_BITWISE_AND) {
  897. return FALSE;
  898. }
  899. ParseIndirection(&pTypesInfo->IndLevel,
  900. &dwSize,
  901. &pTypesInfo->Flags,
  902. NULL,
  903. NULL);
  904. // This is a hack for the busted way that sortpp parses
  905. // data. New types do not inherit the pointer size
  906. // properly. We also can't inherit it at the top
  907. // since this might be a pointer to a pointer. So what
  908. // we do is try to parse this as a pointer, and if the IndLevel
  909. // increases we know this is a pointer so do nothing. If the IndLevel
  910. // doesn't increase, this is not a pointer so inherite the pointer attributes
  911. // from the parent.
  912. ASSERT(pTypesInfo->IndLevel >= IndLevel);
  913. if (pTypesInfo->IndLevel == IndLevel) {
  914. // inherite is ptr64 attribute from the base type.
  915. pTypesInfo->Flags |= (TypesInfo.Flags & BTI_PTR64);
  916. }
  917. if (CurrentToken()->TokenType != TK_IDENTIFIER) {
  918. return FALSE;
  919. }
  920. //
  921. // Get the name of the new typedef
  922. //
  923. if (CopyToken(pTypesInfo->TypeName,
  924. CurrentToken()->Name,
  925. sizeof(pTypesInfo->TypeName)-1
  926. )
  927. >= sizeof(pTypesInfo->TypeName)) {
  928. return FALSE;
  929. }
  930. ConsumeToken();
  931. //
  932. // Handle an array of the type
  933. //
  934. while (CurrentToken()->TokenType == TK_LSQUARE) {
  935. DWORD dwIndex;
  936. if (!GetArrayIndex(&dwIndex)) {
  937. return FALSE;
  938. }
  939. if (dwIndex == 0) { // a[] is really *a
  940. pTypesInfo->IndLevel++;
  941. } else {
  942. pTypesInfo->Flags |= BTI_ISARRAY;
  943. pTypesInfo->dwArrayElements = dwIndex;
  944. pTypesInfo->dwBaseSize = dwSize;
  945. dwSize = dwSize * dwIndex;
  946. }
  947. }
  948. if (pTypesInfo->IndLevel) {
  949. if (pTypesInfo->Flags & BTI_PTR64) {
  950. pTypesInfo->Size = SIZEOFPOINTER64;
  951. pTypesInfo->iPackSize = SIZEOFPOINTER64;
  952. } else {
  953. pTypesInfo->Size = SIZEOFPOINTER;
  954. pTypesInfo->iPackSize = SIZEOFPOINTER;
  955. }
  956. pTypesInfo->Flags |= BTI_POINTERDEP;
  957. } else {
  958. pTypesInfo->Size = dwSize;
  959. }
  960. switch (CurrentToken()->TokenType) {
  961. case TK_EOS:
  962. return TRUE;
  963. case TK_COMMA:
  964. //
  965. // There is a list of types derived from the base type
  966. // Add the current type in and loop to parse the next
  967. // type.
  968. //
  969. if (!AddNewType(pTypesInfo, TypeDefsList)) {
  970. return FALSE;
  971. }
  972. ConsumeToken(); // consume the ','
  973. break;
  974. default:
  975. return FALSE;
  976. }
  977. }
  978. }
  979. BOOL
  980. ParseFuncTypes(
  981. PTYPESINFO pTypesInfo,
  982. BOOL fDllImport
  983. )
  984. /*++
  985. Routine Description:
  986. Parses a C-language statement if it is a function declaration:
  987. <mod> type <*> <mod> Name ( type <arg1>, type <arg2>, type <argn> )
  988. <mod> type <*> (<mod> * Name ) ( type <arg1>, type <arg2>, type <argn> )
  989. (Note that we don't deal with extraneous parens very well, and don't
  990. handle function pointers as return types.
  991. e.g. "void (*(*foo)(void))(void);" ).
  992. Arguments:
  993. pTypesInfo -- OUT ptr to info about the type
  994. fDllImport -- TRUE if __declspec(dllimport) already consumed
  995. Return Value:
  996. TRUE if the statement is a function declaration
  997. FALSE if the statement is not a function declaration or some kind of error
  998. --*/
  999. {
  1000. char *pName;
  1001. char *ps;
  1002. char *pArgName;
  1003. BOOL bFnPtr = FALSE;
  1004. ULONG ArgNum = 0;
  1005. int IndLevel = 0;
  1006. int ArgIndLevel;
  1007. int Len;
  1008. TYPESINFO ti;
  1009. PFUNCINFO pfuncinfo;
  1010. BUFALLOCINFO bufallocinfo;
  1011. int OldTokenIndex;
  1012. char NoNameArg[32];
  1013. PKNOWNTYPES pkt;
  1014. memset(pTypesInfo, 0, sizeof(TYPESINFO));
  1015. BufAllocInit(&bufallocinfo, pTypesInfo->Members, sizeof(pTypesInfo->Members), 0);
  1016. pfuncinfo = NULL;
  1017. if (fDllImport) {
  1018. //
  1019. // Declaration has __declspec(dllimport). Genthnk should emit
  1020. // __declspec(dllexport) in the function definition.
  1021. //
  1022. pTypesInfo->Flags |= BTI_DLLEXPORT;
  1023. }
  1024. // for functions, the first token is ret type
  1025. if (IsTokenSeparator() && CurrentToken()->TokenType != TK_LPAREN) {
  1026. //
  1027. // First token isn't even an identifier - bail out.
  1028. //
  1029. return FALSE;
  1030. }
  1031. // There can be multiple __declspec's here - run through them all
  1032. do {
  1033. ConsumeDeclSpecOpt(TRUE, FALSE, &fDllImport, NULL, NULL);
  1034. } while (CurrentToken()->TokenType == TK_DECLSPEC);
  1035. //
  1036. // Remember the index of the first token which describes the return type.
  1037. //
  1038. OldTokenIndex = CurrentTokenIndex;
  1039. if (CurrentToken()->TokenType == TK_LPAREN) {
  1040. // This is this start of a typedef (pfn)()
  1041. // where the pfn has an implecit return type of
  1042. // int.
  1043. strcpy(pTypesInfo->FuncRet, "int");
  1044. goto ImplicitReturnType;
  1045. }
  1046. if (ConsumeDirectionOpt() != TK_NONE && bDebug) {
  1047. // A struct element had a direction on it. Ignore it and
  1048. // warn the user.
  1049. fprintf(stderr, "Warning: IN and OUT are ignored on function return types. %s line %d\n", SourceFileName, StatementLineNumber);
  1050. }
  1051. ConsumeConstVolatileOpt();
  1052. if (!GetExistingType(&ti, NULL, NULL)) {
  1053. ErrMsg("pft.rtype: unknown return type\n");
  1054. DumpLexerOutput(OldTokenIndex);
  1055. return FALSE;
  1056. }
  1057. // get indir for ret type
  1058. ParseIndirection(&pTypesInfo->RetIndLevel, NULL, NULL, NULL, NULL);
  1059. // Copy out ret type to FuncRet
  1060. if (!UnlexToText(pTypesInfo->FuncRet, sizeof(pTypesInfo->FuncRet),
  1061. OldTokenIndex, CurrentTokenIndex)) {
  1062. return FALSE;
  1063. }
  1064. ConsumeDeclSpecOpt(TRUE, FALSE, &fDllImport, NULL, NULL);
  1065. if (fDllImport) {
  1066. // Declaration has __declspec(dllimport). Genthnk should emit
  1067. // __declspec(dllexport) in the function definition.
  1068. //
  1069. pTypesInfo->Flags |= BTI_DLLEXPORT;
  1070. }
  1071. // if open paren, assume a fn pointer
  1072. ImplicitReturnType:
  1073. if (CurrentToken()->TokenType == TK_LPAREN) {
  1074. bFnPtr = TRUE;
  1075. ConsumeToken();
  1076. }
  1077. // include cdecl, stdcall, save as FuncMod
  1078. switch (CurrentToken()->TokenType) {
  1079. case TK_CDECL:
  1080. Len = CopyToken(pTypesInfo->FuncMod, szCDECL, sizeof(pTypesInfo->FuncMod) - 1);
  1081. if (Len >= sizeof(pTypesInfo->FuncMod) - 1) {
  1082. return FALSE;
  1083. }
  1084. ConsumeToken();
  1085. break;
  1086. case TK_FASTCALL:
  1087. Len = CopyToken(pTypesInfo->FuncMod, sz__FASTCALL, sizeof(pTypesInfo->FuncMod) - 1);
  1088. if (Len >= sizeof(pTypesInfo->FuncMod) - 1) {
  1089. return FALSE;
  1090. }
  1091. ConsumeToken();
  1092. break;
  1093. case TK_STDCALL:
  1094. Len = CopyToken(pTypesInfo->FuncMod, szSTDCALL, sizeof(pTypesInfo->FuncMod) - 1);
  1095. if (Len >= sizeof(pTypesInfo->FuncMod) - 1) {
  1096. return FALSE;
  1097. }
  1098. ConsumeToken();
  1099. //
  1100. // some funky ole include has:
  1101. // "BOOL (__stdcall __stdcall *pfnContinue)(DWORD)"
  1102. //
  1103. if (CurrentToken()->TokenType == TK_STDCALL) {
  1104. ConsumeToken();
  1105. }
  1106. break;
  1107. default:
  1108. break;
  1109. }
  1110. pTypesInfo->TypeKind = TypeKindFunc;
  1111. pTypesInfo->dwMemberSize = 0;
  1112. //
  1113. // count indir on function
  1114. //
  1115. if (bFnPtr) {
  1116. while (CurrentToken()->TokenType == TK_STAR ||
  1117. CurrentToken()->TokenType == TK_BITWISE_AND) {
  1118. IndLevel++;
  1119. ConsumeToken();
  1120. }
  1121. }
  1122. //
  1123. // We expect the next token to be the func name.
  1124. //
  1125. if (CurrentToken()->TokenType != TK_RPAREN &&
  1126. CurrentToken()->TokenType != TK_IDENTIFIER) {
  1127. return FALSE;
  1128. }
  1129. pName = (bFnPtr && CurrentToken()->TokenType == TK_RPAREN) ? "" : CurrentToken()->Name;
  1130. strcpy(pTypesInfo->BaseName, szFUNC);
  1131. // look for beg of ArgList
  1132. ConsumeToken();
  1133. if (bFnPtr && CurrentToken()->TokenType == TK_RPAREN) {
  1134. ConsumeToken();
  1135. }
  1136. if (CurrentToken()->TokenType != TK_LPAREN) {
  1137. return FALSE;
  1138. }
  1139. ConsumeToken(); // consume the '('
  1140. //
  1141. // copy out the ArgList
  1142. //
  1143. while (CurrentToken()->TokenType != TK_EOS) {
  1144. if (CurrentToken()->TokenType == TK_RPAREN) {
  1145. break;
  1146. }
  1147. ArgIndLevel = 0;
  1148. // ([mod] type [mod] [*] [mod] [ArgName] , ...)
  1149. bFnPtr = FALSE;
  1150. // skip register keywords all together
  1151. if (CurrentToken()->TokenType == TK_REGISTER) {
  1152. ConsumeToken();
  1153. }
  1154. //
  1155. // Remember where we are in the parse
  1156. //
  1157. OldTokenIndex = CurrentTokenIndex;
  1158. //
  1159. // Allocate a new FUNCINFO struct for this parameter
  1160. //
  1161. pfuncinfo = AllocFuncInfoAndLink(&bufallocinfo, pfuncinfo);
  1162. if (!pTypesInfo->pfuncinfo) {
  1163. pTypesInfo->pfuncinfo = pfuncinfo;
  1164. }
  1165. if (CurrentToken()->TokenType == TK_VARGS) {
  1166. ps = BufPointer(&bufallocinfo);
  1167. pfuncinfo->sType = ps;
  1168. strcpy(ps, szVARGS);
  1169. BufAllocate(&bufallocinfo, strlen(szVARGS)+1);
  1170. ConsumeToken();
  1171. break;
  1172. }
  1173. // grab the IN, OUT, or 'IN OUT', if present
  1174. pfuncinfo->tkDirection = ConsumeDirectionOpt();
  1175. pfuncinfo->tkPreMod = ConsumeConstVolatileOpt();
  1176. if (!GetExistingType(&ti, &bFnPtr, &pkt)) {
  1177. ErrMsg("pft.args: unknown argument type at %d\n", OldTokenIndex);
  1178. return FALSE;
  1179. }
  1180. pfuncinfo->pkt = pkt;
  1181. // enter fp member as a typedef to store args and rettype
  1182. if (bFnPtr) {
  1183. TYPESINFO tiTmp;
  1184. tiTmp = ti;
  1185. tiTmp.pfuncinfo = RelocateTypesInfo(tiTmp.Members, &ti);
  1186. tiTmp.Flags |= BTI_CONTAINSFUNCPTR;
  1187. Len = CreatePseudoName(tiTmp.TypeName, ti.TypeName);
  1188. if (!Len) {
  1189. return FALSE;
  1190. }
  1191. pkt = AddNewType(&tiTmp, TypeDefsList);
  1192. if (NULL == pkt) {
  1193. return FALSE;
  1194. }
  1195. ps = BufPointer(&bufallocinfo);
  1196. pfuncinfo->sType = ps;
  1197. strcpy(ps, tiTmp.TypeName);
  1198. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1199. pArgName = ti.TypeName;
  1200. goto aftername;
  1201. } else {
  1202. DWORD Flags = 0;
  1203. // skip indirection
  1204. ParseIndirection(&pfuncinfo->IndLevel,
  1205. NULL,
  1206. &Flags,
  1207. &pfuncinfo->tkPrePostMod,
  1208. &pfuncinfo->tkPostMod
  1209. );
  1210. if (Flags & BTI_PTR64) {
  1211. pfuncinfo->fIsPtr64 = TRUE;
  1212. }
  1213. ps = BufPointer(&bufallocinfo);
  1214. pfuncinfo->sType = ps;
  1215. strcpy(ps, ti.TypeName);
  1216. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1217. //
  1218. // If the type of the parameter has an explicit
  1219. // struct/union/enum keyword, pass that info on to
  1220. // genthnk. ie. if the parameter type is like
  1221. // 'struct typename argname', set tkSUE to TK_STRUCT.
  1222. //
  1223. if (strcmp(ti.BaseName, szSTRUCT) == 0) {
  1224. pfuncinfo->tkSUE = TK_STRUCT;
  1225. } else if (strcmp(ti.BaseName, szUNION) == 0) {
  1226. pfuncinfo->tkSUE = TK_UNION;
  1227. } else if (strcmp(ti.BaseName, szENUM) == 0) {
  1228. pfuncinfo->tkSUE = TK_ENUM;
  1229. } else {
  1230. pfuncinfo->tkSUE = TK_NONE;
  1231. }
  1232. }
  1233. // if no argument name present, create one
  1234. switch (CurrentToken()->TokenType) {
  1235. case TK_RPAREN:
  1236. case TK_LSQUARE:
  1237. case TK_COMMA:
  1238. // but null arg list doesn't have any name
  1239. if (CurrentToken()->TokenType == TK_COMMA ||
  1240. ArgNum ||
  1241. ti.IndLevel ||
  1242. pfuncinfo->IndLevel ||
  1243. strcmp(ti.BasicType, szVOID) ) {
  1244. pArgName = NoNameArg;
  1245. sprintf(NoNameArg, "_noname%x", ArgNum++);
  1246. } else {
  1247. pArgName = NULL;
  1248. }
  1249. break;
  1250. case TK_IDENTIFIER:
  1251. pArgName = CurrentToken()->Name;
  1252. if (ArgNum == 0 &&
  1253. pfuncinfo->IndLevel == 1 &&
  1254. strcmp(pArgName, "This") == 0) {
  1255. //
  1256. // This is the first arg and it is a pointer with name 'This'.
  1257. // Assume it is a MIDL-generated proxy prototype.
  1258. //
  1259. pfuncinfo->tkDirection = TK_IN;
  1260. }
  1261. ConsumeToken();
  1262. break;
  1263. default:
  1264. return FALSE;
  1265. }
  1266. aftername:
  1267. if (pArgName) {
  1268. //
  1269. // Copy the argument name from pArgName into pfuncinfo->sName.
  1270. //
  1271. ps = BufPointer(&bufallocinfo);
  1272. pfuncinfo->sName = ps;
  1273. strcpy(ps, pArgName);
  1274. }
  1275. //
  1276. // Handle parameter which is a single-dimension array by copying the
  1277. // entire string from '[' to ']' (inclusive)
  1278. // ie. int foo(int i[3])
  1279. //
  1280. if (CurrentToken()->TokenType == TK_LSQUARE) {
  1281. int OldCurrentTokenIndex = CurrentTokenIndex;
  1282. int ArgNameLen = strlen(ps);
  1283. do {
  1284. ConsumeToken();
  1285. } while (CurrentToken()->TokenType != TK_RSQUARE &&
  1286. CurrentToken()->TokenType != TK_EOS);
  1287. if (CurrentToken()->TokenType == TK_EOS) {
  1288. // Reject - unmatched '[' and ']'
  1289. return FALSE;
  1290. }
  1291. // if (CurrentTokenIndex - OldCurrentTokenIndex == 1) {
  1292. //
  1293. // Found: empty array bounds '[]'. Bump IndLevel and
  1294. // don't append the '[]' to the parameter name.
  1295. //
  1296. pfuncinfo->IndLevel++;
  1297. // } else if (!UnlexToText(ps + ArgNameLen,
  1298. // BufGetFreeSpace(&bufallocinfo) - ArgNameLen,
  1299. // OldCurrentTokenIndex,
  1300. // CurrentTokenIndex+1)) {
  1301. // ErrMsg("pft: args list too long\n");
  1302. // return FALSE;
  1303. // }
  1304. ConsumeToken();
  1305. }
  1306. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1307. //bug bug , hack hack, danger danger
  1308. if (CurrentToken()->TokenType == TK_ASSIGN) {
  1309. //Header is using the C++ syntax of assigning
  1310. //a default value to a argument.
  1311. //This will be skipped. Skip until a TK_COMMA, TK_EOS, TK_RPAREN
  1312. ConsumeToken();
  1313. while(CurrentToken()->TokenType != TK_COMMA &&
  1314. CurrentToken()->TokenType != TK_EOS &&
  1315. CurrentToken()->TokenType != TK_RPAREN) {
  1316. ConsumeToken();
  1317. }
  1318. }
  1319. if (CurrentToken()->TokenType == TK_RPAREN) {
  1320. break;
  1321. } else { // more args to go, add comma delimiter
  1322. ConsumeToken();
  1323. }
  1324. }
  1325. if (CurrentToken()->TokenType != TK_RPAREN) {
  1326. ErrMsg("pft: unknown syntax for fn args\n");
  1327. return FALSE;
  1328. }
  1329. ConsumeToken(); // consume the ')'
  1330. pTypesInfo->IndLevel = IndLevel;
  1331. pTypesInfo->Size = 4;
  1332. pTypesInfo->iPackSize = 4;
  1333. strcpy(pTypesInfo->BasicType, szFUNC);
  1334. if (CopyToken(pTypesInfo->TypeName,
  1335. pName,
  1336. sizeof(pTypesInfo->TypeName)-1
  1337. )
  1338. >= sizeof(pTypesInfo->TypeName) ) {
  1339. return FALSE;
  1340. }
  1341. if (pfuncinfo == NULL) {
  1342. //
  1343. // No args encountered - create VOID args now
  1344. //
  1345. pfuncinfo = AllocFuncInfoAndLink(&bufallocinfo, pfuncinfo);
  1346. ps = BufPointer(&bufallocinfo);
  1347. strcpy(ps, szVOID);
  1348. pfuncinfo->sType = ps;
  1349. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1350. pTypesInfo->pfuncinfo = pfuncinfo;
  1351. }
  1352. pTypesInfo->dwMemberSize = bufallocinfo.dwLen;
  1353. return TRUE;
  1354. }
  1355. BOOL
  1356. ParseStructTypes(
  1357. PTYPESINFO pTypesInfo
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. Parses a C-language statement if it is struct/union/enum declaration.
  1362. struct|union|enum NewName <{}>
  1363. struct NewName : <permission> BaseName <{}>
  1364. (Note that we don't deal with extraneous parens very well)
  1365. Arguments:
  1366. pTypesInfo -- OUT ptr to info about the type
  1367. Return Value:
  1368. TRUE if the statement is a struct/union/enum
  1369. FALSE if the statement is not a s/u/e, or some other error
  1370. --*/
  1371. {
  1372. TOKENTYPE FirstToken;
  1373. BOOL bEnum = FALSE;
  1374. BOOL bUnion = FALSE;
  1375. DWORD dwOldScopeLevel = dwScopeLevel;
  1376. BOOL IsGuidDefined = FALSE;
  1377. memset(pTypesInfo, 0, sizeof(TYPESINFO));
  1378. //
  1379. // Match one of: STRUCT, UNION, or ENUM
  1380. //
  1381. FirstToken = CurrentToken()->TokenType;
  1382. switch (FirstToken) {
  1383. case TK_STRUCT:
  1384. break;
  1385. case TK_UNION:
  1386. bUnion = TRUE;
  1387. break;
  1388. case TK_ENUM:
  1389. bEnum = TRUE;
  1390. break;
  1391. default:
  1392. goto retfail; // no match
  1393. }
  1394. ConsumeToken();
  1395. // BasicType is "struct", "union", or "enum"
  1396. if (CopyToken(pTypesInfo->BasicType,
  1397. TokenString[FirstToken],
  1398. sizeof(pTypesInfo->BasicType)-1
  1399. )
  1400. >= sizeof(pTypesInfo->BasicType) ) {
  1401. goto retfail;
  1402. }
  1403. strcpy(pTypesInfo->BaseName, pTypesInfo->BasicType);
  1404. //handle declspecs
  1405. if (!bUnion && !bEnum) {
  1406. while(ConsumeDeclSpecOpt(FALSE, FALSE, NULL, &IsGuidDefined, &(pTypesInfo->gGuid)));
  1407. if (IsGuidDefined) pTypesInfo->Flags |= BTI_HASGUID;
  1408. }
  1409. switch (CurrentToken()->TokenType) {
  1410. case TK_IDENTIFIER:
  1411. {
  1412. if (CopyToken(pTypesInfo->TypeName,
  1413. CurrentToken()->Name,
  1414. sizeof(pTypesInfo->BasicType)-1
  1415. )
  1416. >= sizeof(pTypesInfo->BasicType) ) {
  1417. goto retfail;
  1418. }
  1419. ConsumeToken();
  1420. break;
  1421. }
  1422. case TK_LBRACE: // anonymous struct/union/enum
  1423. if (!CreatePseudoName(pTypesInfo->TypeName, TokenString[FirstToken])) {
  1424. //
  1425. // call failed - probably buffer overflow
  1426. //
  1427. goto retfail;
  1428. }
  1429. pTypesInfo->Flags |= BTI_ANONYMOUS;
  1430. break;
  1431. default:
  1432. //
  1433. // STRUCT/UNION/ENUM followed by something other than an identifier
  1434. // or a '{'.
  1435. //
  1436. goto retfail;
  1437. }
  1438. //
  1439. // Process the contents of the curly braces, if present.
  1440. //
  1441. switch (CurrentToken()->TokenType) {
  1442. case TK_EOS:
  1443. goto retsuccess;
  1444. case TK_LBRACE:
  1445. {
  1446. if (bEnum) {
  1447. if(CopyEnumMembers(pTypesInfo)) goto retsuccess;
  1448. else goto retfail;
  1449. }
  1450. if(CopyStructMembers(pTypesInfo, bUnion, NULL)) goto retsuccess;
  1451. else goto retfail;
  1452. }
  1453. case TK_COLON: //entering a derived struct
  1454. if (bEnum || bUnion) goto retfail;
  1455. ConsumeToken();
  1456. //look for base skipping public, private, and protected
  1457. {
  1458. PTOKEN pToken;
  1459. BOOL bRetVal;
  1460. PTYPEINFOELEMENT pMemFuncs;
  1461. PKNOWNTYPES BaseType;
  1462. pToken = CurrentToken();
  1463. if (pToken->TokenType != TK_IDENTIFIER) goto retfail;
  1464. if (strcmp(pToken->Name, "public") == 0 ||
  1465. strcmp(pToken->Name, "private") == 0 ||
  1466. strcmp(pToken->Name, "protected") == 0) {
  1467. ConsumeToken();
  1468. }
  1469. //look for base
  1470. if (CopyToken(pTypesInfo->BaseType,
  1471. CurrentToken()->Name,
  1472. sizeof(pTypesInfo->BasicType)-1
  1473. )
  1474. >= sizeof(pTypesInfo->BasicType) ) {
  1475. goto retfail;
  1476. }
  1477. //lookup the base in structures
  1478. BaseType = GetNameFromTypesList(StructsList,pTypesInfo->BaseType);
  1479. if (NULL == BaseType) {
  1480. //ErrMsg("Base type is unknown or not a structure\n");
  1481. goto retfail;
  1482. }
  1483. //look for opening brace or EOS
  1484. ConsumeToken();
  1485. if (CurrentToken()->TokenType == TK_EOS) goto retsuccess;
  1486. if (CurrentToken()->TokenType != TK_LBRACE) goto retfail;
  1487. if (CopyStructMembers(pTypesInfo, FALSE, BaseType)) goto retsuccess;
  1488. else goto retfail;
  1489. }
  1490. default:
  1491. break;
  1492. }
  1493. goto retsuccess;
  1494. retfail:
  1495. dwScopeLevel = dwOldScopeLevel;
  1496. return FALSE;
  1497. retsuccess:
  1498. dwScopeLevel = dwOldScopeLevel;
  1499. return TRUE;
  1500. }
  1501. BOOL
  1502. CopyEnumMembers(
  1503. PTYPESINFO pTypesInfo
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. Scans over members of an enumeration declaration. Nobody cares
  1508. about the actual names and values, so they are simply skipped over
  1509. until the matching '}' is found.
  1510. Arguments:
  1511. pTypesInfo -- OUT ptr to info about the type
  1512. Return Value:
  1513. TRUE if the declaration is parsed OK
  1514. FALSE if the statement is mis-parsed, or some other error
  1515. --*/
  1516. {
  1517. DWORD *pdwSize = &(pTypesInfo->Size);
  1518. DWORD *pdwPackSize = &(pTypesInfo->iPackSize);
  1519. dwScopeLevel++;
  1520. if (CurrentToken()->TokenType != TK_LBRACE) {
  1521. return FALSE;
  1522. } else {
  1523. ConsumeToken();
  1524. }
  1525. //
  1526. // Find the '}' which ends the enumeration declaration
  1527. //
  1528. while (CurrentToken()->TokenType != TK_RBRACE) {
  1529. ConsumeToken();
  1530. }
  1531. ConsumeToken(); // consume the '}', too
  1532. *pdwSize = sizeof(int); // enum
  1533. *pdwPackSize = sizeof(int); // enum
  1534. return TRUE;
  1535. }
  1536. // How sortpp computes packing sizes:
  1537. //
  1538. // * Each member has a packing size which is
  1539. // - size of a appropriate pointer if member is a pointer
  1540. // - packing size of its base type
  1541. // * The packing size of struc or union is min(packing_size_of_largest_member,
  1542. // current_packing_size_when_struct_defined)
  1543. // * Each member in a struct is aligned according to min(current_packing_size,
  1544. // member_packing_size).
  1545. // * All pointers have size sizeof(void *) except __ptr64 pointers which
  1546. // have a size sizeof(PVOID64)
  1547. // * bit fields are coallessed until
  1548. // - the end of the struct
  1549. // - a non bit field member
  1550. // - a bit field member, but of different base type size
  1551. // * char s[] as the last member of a struct adds nothing to the size of the
  1552. // struct and should not be aligned.
  1553. // * each member of a union is packed at offset 0.
  1554. BOOL
  1555. pCopyStructMembers(
  1556. PTYPESINFO pTypesInfo,
  1557. BOOL bUnion,
  1558. PTYPEINFOELEMENT * ppMemberFuncs,
  1559. DWORD Size,
  1560. DWORD iPackSize
  1561. )
  1562. /*++
  1563. Routine Description:
  1564. Copies out struct members, verifying type of each member.
  1565. { [mod] type [*] varname; [mod] type [*] varname; ...}
  1566. { {varname, varname, ...}
  1567. Assumes CurrentToken points at the '{' for the member list.
  1568. Also determines the size of the struct/union.
  1569. Arguments:
  1570. pTypesInfo -- OUT ptr to info about the type
  1571. bUnion -- TRUE if parsing union, FALSE if parsing STRUCT.
  1572. ppMemberFuncs -- OUT returns a list of virtual member functions or NULL.
  1573. Return Value:
  1574. TRUE if the declaration is parsed OK
  1575. FALSE if the statement is mis-parsed, or some other error
  1576. --*/
  1577. {
  1578. char *psMemBuf = pTypesInfo->Members;
  1579. DWORD *pdwSize = &(pTypesInfo->Size);
  1580. DWORD *pdwPackSize = &(pTypesInfo->iPackSize);
  1581. int Len;
  1582. BOOL bFnPtr;
  1583. TYPESINFO ti;
  1584. DWORD dw;
  1585. DWORD dwBase; // running size of struct element
  1586. DWORD dwElemSize; // size of a particular element
  1587. DWORD dwBaseTypeSize; // size of basic type of element
  1588. DWORD dwBits; // # bits in a bitfield element
  1589. DWORD dwBitsTotal; // running # bits for string of elemnts
  1590. DWORD dwBitsTypeSize; // bit fields base type size
  1591. BOOL bForceOutBits = FALSE;
  1592. BOOL bTailPointer = FALSE;
  1593. DWORD dwLastPackSize = 0;
  1594. DWORD dwLastSize = 0;
  1595. PMEMBERINFO pmeminfo;
  1596. BUFALLOCINFO bufallocinfo;
  1597. char *ps;
  1598. DWORD Flags;
  1599. DWORD dwIndex;
  1600. int ParenDepth = 0;
  1601. PTYPEINFOELEMENT pMethods = NULL;
  1602. DWORD dwMethodNumber = 0;
  1603. PKNOWNTYPES pkt;
  1604. if (ppMemberFuncs != NULL) *ppMemberFuncs = NULL;
  1605. *pdwSize = Size; // initialize size of structure
  1606. *pdwPackSize = iPackSize; // initialize packing alignment
  1607. dwLastSize = Size;
  1608. dwLastPackSize = iPackSize;
  1609. BufAllocInit(&bufallocinfo, psMemBuf, sizeof(pTypesInfo->Members), 0);
  1610. pmeminfo = NULL;
  1611. pTypesInfo->TypeKind = TypeKindStruct;
  1612. pTypesInfo->dwMemberSize = 0;
  1613. bFnPtr = FALSE;
  1614. // loop over members of the structure or union
  1615. dwBitsTotal = 0;
  1616. dwBitsTypeSize = 0;
  1617. if (CurrentToken()->TokenType != TK_LBRACE) {
  1618. return FALSE;
  1619. }
  1620. ConsumeToken();
  1621. while (CurrentToken()->TokenType != TK_RBRACE) {
  1622. int OldCurrentTokenIndex = CurrentTokenIndex;
  1623. if (bDebug)
  1624. DumpLexerOutput(CurrentTokenIndex);
  1625. //strip off permission attributes
  1626. //{public private protected} :
  1627. while(CurrentToken()->TokenType == TK_IDENTIFIER &&
  1628. (strcmp(CurrentToken()->Name, "public") == 0 ||
  1629. strcmp(CurrentToken()->Name, "private") == 0 ||
  1630. strcmp(CurrentToken()->Name, "protected") == 0
  1631. ))
  1632. {
  1633. ConsumeToken();
  1634. if (CurrentToken()->TokenType != TK_COLON) return FALSE;
  1635. ConsumeToken();
  1636. if (CurrentToken()->TokenType == TK_RBRACE) goto done;
  1637. }
  1638. if (!bUnion &&
  1639. ppMemberFuncs != NULL &&
  1640. CurrentToken()->TokenType == TK_IDENTIFIER &&
  1641. strcmp(CurrentToken()->Name, "virtual") == 0) {
  1642. PTYPESINFO pFuncInfo;
  1643. int TokenNumber = CurrentTokenIndex;
  1644. ConsumeConstVolatileOpt();
  1645. pFuncInfo = GenHeapAlloc(sizeof(TYPESINFO));
  1646. if (pFuncInfo == NULL) ExitErrMsg(FALSE, "Out of memory!\n");
  1647. ConsumeToken();
  1648. //virtual method
  1649. if (!ParseFuncTypes(pFuncInfo, FALSE)) {
  1650. ErrMsg("Unable to parse method %u of %s\n", dwMethodNumber, pTypesInfo->TypeName);
  1651. DumpLexerOutput(TokenNumber);
  1652. return FALSE;
  1653. }
  1654. pMethods = TypeInfoElementAllocateLink(ppMemberFuncs, pMethods, pFuncInfo);
  1655. //remove extra ;
  1656. if (CurrentToken()->TokenType == TK_SEMI)
  1657. ConsumeToken();
  1658. //remove extra = 0;
  1659. else if (CurrentToken()->TokenType == TK_ASSIGN) {
  1660. ConsumeToken();
  1661. //parsing 0;
  1662. if (!(CurrentToken()->TokenType == TK_NUMBER &&
  1663. CurrentToken()->Value == 0)) return FALSE;
  1664. ConsumeToken();
  1665. //parsing ;
  1666. if (CurrentToken()->TokenType != TK_SEMI) return FALSE;
  1667. ConsumeToken();
  1668. }
  1669. else return FALSE; //fail
  1670. dwMethodNumber++;
  1671. continue;
  1672. }
  1673. if (ConsumeDirectionOpt() != TK_NONE && bDebug) {
  1674. // A struct element had a direction on it. Ignore it and
  1675. // warn the user.
  1676. fprintf(stderr, "Warning: IN and OUT are ignored on struct members. %s line %d\n", SourceFileName, StatementLineNumber);
  1677. }
  1678. ConsumeConstVolatileOpt();
  1679. pmeminfo = AllocMemInfoAndLink(&bufallocinfo, pmeminfo);
  1680. if (pmeminfo == NULL) {
  1681. ErrMsg("CopyStructMembers: No memberinfo\n");
  1682. return FALSE;
  1683. }
  1684. if (!GetExistingType(&ti, &bFnPtr, &pkt)) {
  1685. ErrMsg("csm: unknown Type %d\n", OldCurrentTokenIndex);
  1686. return FALSE;
  1687. }
  1688. pmeminfo->pkt = pkt;
  1689. // enter function pointer member as a typedef to store args, rettype
  1690. if (bFnPtr) {
  1691. TYPESINFO tiTmp;
  1692. ti.Flags |= BTI_CONTAINSFUNCPTR;
  1693. tiTmp = ti;
  1694. tiTmp.pfuncinfo = RelocateTypesInfo(tiTmp.Members, &ti);
  1695. Len = CreatePseudoName(tiTmp.TypeName, ti.TypeName);
  1696. if (!Len) {
  1697. return FALSE;
  1698. }
  1699. tiTmp.Size = ti.Size;
  1700. tiTmp.iPackSize = ti.iPackSize;
  1701. pkt = AddNewType(&tiTmp, TypeDefsList);
  1702. if (NULL == pkt) {
  1703. return FALSE;
  1704. }
  1705. ps = BufPointer(&bufallocinfo);
  1706. pmeminfo->sName = ps;
  1707. strcpy(ps, ti.TypeName);
  1708. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1709. pmeminfo->pkt = pkt;
  1710. }
  1711. /*else {
  1712. ////////////////////////////////////////////////////////////////
  1713. //This type has no members for it, do no process further.
  1714. /////////////////////////////////////////////////////////////////
  1715. if (CurrentToken()->TokenType == TK_SEMI) {
  1716. ConsumeToken();
  1717. continue;
  1718. }
  1719. }*/
  1720. //
  1721. // If the member contains a function pointer, then mark
  1722. // this struct has containing a function pointer
  1723. // Also mark if member is pointer dependent.
  1724. pTypesInfo->Flags |= ((ti.Flags & BTI_CONTAINSFUNCPTR) | (ti.Flags & BTI_POINTERDEP));
  1725. //
  1726. // Union arm initialization
  1727. dwBaseTypeSize = ti.iPackSize;
  1728. if ((dwBitsTotal > 0) && (dwBaseTypeSize != dwBitsTypeSize)) {
  1729. //
  1730. // Determine size of bitfields
  1731. //
  1732. dw = (dwBitsTotal + ((dwBitsTypeSize*8)-1)) / (dwBitsTypeSize*8);
  1733. *pdwSize = *pdwSize + PackPackingSize(bUnion ? 0 : *pdwSize,
  1734. dw*dwBitsTypeSize,
  1735. dwBitsTypeSize);
  1736. dwBitsTotal = 0;
  1737. }
  1738. dwBitsTypeSize = dwBaseTypeSize;
  1739. // element initialization
  1740. dwBase = ti.Size;
  1741. dwBits = 0;
  1742. bTailPointer = FALSE;
  1743. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1744. PackPaddingSize(*pdwSize,
  1745. dwBaseTypeSize);
  1746. //
  1747. // Copy in the typename
  1748. //
  1749. ps = BufPointer(&bufallocinfo);
  1750. pmeminfo->sType = ps;
  1751. strcpy(ps, ti.TypeName);
  1752. BufAllocate(&bufallocinfo, strlen(ps)+1);
  1753. //
  1754. // Skip just past the terminating ';' for this member and
  1755. // figure out any size modifers to size of the base type.
  1756. //
  1757. while (CurrentToken()->TokenType != TK_SEMI) {
  1758. PMEMBERINFO pmeminfoNew;
  1759. switch (CurrentToken()->TokenType) {
  1760. case TK_CONST:
  1761. case TK_VOLATILE:
  1762. ConsumeToken();
  1763. break;
  1764. case TK_COMMA: // comma-separated list
  1765. // update structure packing value
  1766. if (dwBaseTypeSize > *pdwPackSize) {
  1767. *pdwPackSize = dwBaseTypeSize;
  1768. }
  1769. // flush out any bit fields not accounted for
  1770. if ((dwBitsTotal > 0) && (dwBits == 0)) {
  1771. dw = (dwBitsTotal + ((dwBitsTypeSize*8)-1)) /
  1772. (dwBitsTypeSize*8);
  1773. dwElemSize = PackPackingSize(bUnion ? 0 : *pdwSize,
  1774. dw*dwBitsTypeSize, dwBitsTypeSize);
  1775. BumpStructUnionSize(pdwSize, dwElemSize, bUnion);
  1776. dwBitsTotal = 0;
  1777. // recompute offset
  1778. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1779. PackPaddingSize(*pdwSize,
  1780. dwBaseTypeSize);
  1781. }
  1782. // account for member just completed
  1783. if (dwBits == 0) {
  1784. dwElemSize = PackPackingSize(bUnion ? 0 : *pdwSize,
  1785. dwBase,
  1786. dwBaseTypeSize);
  1787. BumpStructUnionSize(pdwSize, dwElemSize, bUnion);
  1788. dwBase = dwBaseTypeSize;
  1789. }
  1790. // update bit field count
  1791. dwBitsTotal = dwBitsTotal + dwBits;
  1792. dwBits = 0;
  1793. // reset tail pointer flag
  1794. bTailPointer = FALSE;
  1795. // allocate space for new structure member and init it
  1796. pmeminfoNew = AllocMemInfoAndLink(&bufallocinfo, pmeminfo);
  1797. if (pmeminfoNew == NULL) {
  1798. ErrMsg("CopyStructMembers: No memberinfo\n");
  1799. return FALSE;
  1800. }
  1801. // Copy over type information from previous meminfo.
  1802. pmeminfoNew->sType = pmeminfo->sType;
  1803. pmeminfoNew->pkt = pmeminfo->pkt;
  1804. pmeminfo = pmeminfoNew;
  1805. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1806. PackPaddingSize(*pdwSize,
  1807. dwBaseTypeSize);
  1808. ConsumeToken();
  1809. break;
  1810. case TK_STAR:
  1811. case TK_BITWISE_AND:
  1812. Flags = 0;
  1813. ParseIndirection(&pmeminfo->IndLevel, NULL, &Flags, NULL, NULL);
  1814. if (Flags & BTI_PTR64) {
  1815. pmeminfo->bIsPtr64 = TRUE;
  1816. dwBase = SIZEOFPOINTER64;
  1817. } else {
  1818. dwBase = SIZEOFPOINTER;
  1819. }
  1820. // If a pointer is present, mark as being pointer dependent.
  1821. if (pmeminfo->IndLevel > 0) pTypesInfo->Flags |= BTI_POINTERDEP;
  1822. dwBaseTypeSize = dwBase;
  1823. if (*pdwPackSize < dwBase) {
  1824. *pdwPackSize = dwBase;
  1825. }
  1826. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1827. PackPaddingSize(*pdwSize,
  1828. dwBaseTypeSize);
  1829. break;
  1830. case TK_LSQUARE: // array declaration
  1831. if (!GetArrayIndex(&dwIndex)) {
  1832. return FALSE;
  1833. }
  1834. if (dwIndex == 0) { // a[] is really *a
  1835. bTailPointer = TRUE;
  1836. dwLastPackSize = *pdwPackSize;
  1837. dwLastSize = *pdwSize;
  1838. dwBase = SIZEOFPOINTER;
  1839. dwBaseTypeSize = SIZEOFPOINTER;
  1840. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1841. PackPaddingSize(*pdwSize,
  1842. dwBaseTypeSize);
  1843. } else {
  1844. pmeminfo->bIsArray = TRUE;
  1845. pmeminfo->ArrayElements = dwIndex;
  1846. dwBase = dwBase * dwIndex;
  1847. }
  1848. break;
  1849. case TK_COLON: // bit field
  1850. ConsumeToken(); // consume the ':'
  1851. if (CurrentToken()->TokenType != TK_NUMBER) {
  1852. return FALSE;
  1853. }
  1854. dwBits = (DWORD)CurrentToken()->Value;
  1855. ConsumeToken(); // consume the TK_NUMBER
  1856. pmeminfo->bIsBitfield = TRUE;
  1857. pmeminfo->BitsRequired = (int)dwBits;
  1858. break;
  1859. case TK_IDENTIFIER:
  1860. ps = BufPointer(&bufallocinfo);
  1861. pmeminfo->sName = ps;
  1862. CopyToken(ps, CurrentToken()->Name, MAX_PATH);
  1863. if (!BufAllocate(&bufallocinfo, strlen(ps)+1)) {
  1864. ErrMsg("csm.members: BufAllocate failed\n");
  1865. return FALSE;
  1866. }
  1867. ConsumeToken();
  1868. break;
  1869. case TK_LPAREN:
  1870. //
  1871. // windows\inc\wingdip.h has a type named GDICALL, which
  1872. // has a member in it with the following declaration:
  1873. // WCHAR (*pDest)[MAX_PATH];
  1874. // We are just going to skip the parens and assume all is OK.
  1875. //
  1876. ParenDepth++;
  1877. ConsumeToken();
  1878. break;
  1879. case TK_RPAREN:
  1880. ParenDepth--;
  1881. ConsumeToken();
  1882. break;
  1883. default:
  1884. ErrMsg("csm.members: unknown type (%d)\n", (int)CurrentToken()->TokenType);
  1885. return FALSE;
  1886. }
  1887. }
  1888. // hit ; at end of a members list
  1889. if (ParenDepth) {
  1890. ErrMsg("csm.members: mismatched parentheses at index %d\n", CurrentTokenIndex);
  1891. return FALSE;
  1892. }
  1893. // update struct packing size to that of largest member
  1894. if (dwBaseTypeSize > *pdwPackSize) {
  1895. *pdwPackSize = dwBaseTypeSize;
  1896. }
  1897. ConsumeToken(); // consume the ';'
  1898. if ((bUnion) || (CurrentToken()->TokenType == TK_SEMI)) {
  1899. dwBitsTotal = dwBitsTotal + dwBits;
  1900. bForceOutBits = TRUE;
  1901. // always force out bits in union arm
  1902. } // or at end of structure
  1903. // flush out any bit fields not accounted for
  1904. if ( (dwBitsTotal > 0) && ( (dwBits == 0) || bForceOutBits) ) {
  1905. dw = (dwBitsTotal + ((dwBitsTypeSize*8)-1)) / (dwBitsTypeSize*8);
  1906. dwElemSize = PackPackingSize(bUnion ? 0 : *pdwSize,
  1907. dw*dwBitsTypeSize, dwBitsTypeSize);
  1908. BumpStructUnionSize(pdwSize, dwElemSize, bUnion);
  1909. dwBitsTotal = 0;
  1910. // recompute offset
  1911. pmeminfo->dwOffset = bUnion ? 0 : *pdwSize +
  1912. PackPaddingSize(*pdwSize,
  1913. dwBaseTypeSize);
  1914. }
  1915. // account for member just completed
  1916. if (dwBits == 0) { // add in last non bit fields
  1917. dwElemSize = PackPackingSize(bUnion ? 0 : *pdwSize,
  1918. dwBase, dwBaseTypeSize);
  1919. BumpStructUnionSize(pdwSize, dwElemSize, bUnion);
  1920. }
  1921. // update bit field counter
  1922. dwBitsTotal = dwBitsTotal + dwBits;
  1923. dwBits = 0;
  1924. }
  1925. done:
  1926. // Advance past the '}'
  1927. if ((CurrentToken()->TokenType == TK_RBRACE)) {
  1928. ConsumeToken();
  1929. }
  1930. // if last member was something like foo[] then we roll back the size
  1931. if ((bTailPointer) && (*pdwSize != 4)) {
  1932. *pdwSize = dwLastSize;
  1933. *pdwPackSize = dwLastPackSize;
  1934. pmeminfo->dwOffset = dwLastSize;
  1935. }
  1936. // pack overall structure on it packing size
  1937. dwBaseTypeSize = PackCurrentPacking() < *pdwPackSize ?
  1938. PackCurrentPacking() : *pdwPackSize;
  1939. if (*pdwSize != 0) { // round up to min(packing level,4)
  1940. dwBase = *pdwSize % dwBaseTypeSize;
  1941. if (dwBase != 0) {
  1942. *pdwSize = *pdwSize + (dwBaseTypeSize - dwBase);
  1943. }
  1944. }
  1945. *pdwPackSize = dwBaseTypeSize;
  1946. pTypesInfo->dwMemberSize = bufallocinfo.dwLen;
  1947. return TRUE;
  1948. }
  1949. PMEMBERINFO
  1950. CatMeminfo(
  1951. BUFALLOCINFO *pBufallocinfo,
  1952. PMEMBERINFO pHead,
  1953. PMEMBERINFO pTail,
  1954. DWORD dwOffset,
  1955. BOOL bStatus
  1956. )
  1957. {
  1958. /*++
  1959. Routine Description:
  1960. Concatinates the member info lists pointed to by pHead and pTail and
  1961. copies them to the memory controled by the BUFALLOCINFO. dwOffset is
  1962. added to the offset for each of the members of the tail list.
  1963. Arguments:
  1964. pBufallocinfo -- [IN] ptr to buffer that represents the destination.
  1965. pHead -- [IN] ptr to the head list.
  1966. pTail -- [IN] ptr to the tail list.
  1967. dwOffset -- [IN] amount to add to the offset of elements in the tail.
  1968. bStatus -- [IN] Should be FALSE on initial call.
  1969. Return Value:
  1970. Head of the new list.
  1971. --*/
  1972. PMEMBERINFO pThis;
  1973. char *pName, *pType;
  1974. if (!bStatus && NULL == pHead) {
  1975. pHead = pTail;
  1976. bStatus = TRUE;
  1977. }
  1978. if (NULL == pHead) return NULL;
  1979. pThis = (PMEMBERINFO)BufAllocate(pBufallocinfo, sizeof(MEMBERINFO));
  1980. if (NULL == pThis) ExitErrMsg(FALSE, "Out of buffer memory! %d", __LINE__);
  1981. *pThis = *pHead;
  1982. if (pHead->sName != NULL) {
  1983. pName = (char *)BufAllocate(pBufallocinfo, strlen(pHead->sName) + 1);
  1984. if (NULL == pName) ExitErrMsg(FALSE, "Out of buffer memory! %d %s", __LINE__, pHead->sName);
  1985. pThis->sName = strcpy(pName, pHead->sName);
  1986. }
  1987. if (pHead->sType != NULL) {
  1988. pType = (char *)BufAllocate(pBufallocinfo, strlen(pHead->sType) + 1);
  1989. if (NULL == pType) ExitErrMsg(FALSE, "Out of buffer memory! %d %s", __LINE__, pHead->sType);
  1990. pThis->sType = strcpy(pType, pHead->sType);
  1991. }
  1992. if (bStatus) pThis->dwOffset += dwOffset;
  1993. pThis->pmeminfoNext = CatMeminfo(pBufallocinfo, pHead->pmeminfoNext, pTail, dwOffset, bStatus);
  1994. return pThis;
  1995. }
  1996. VOID
  1997. FreeTypeInfoList(
  1998. PTYPEINFOELEMENT pThis
  1999. )
  2000. {
  2001. /*++
  2002. Routine Description:
  2003. Frees the memory associated with a TYPEINFOELEMENT.
  2004. Arguments:
  2005. pThis -- [IN] ptr to the list to free.
  2006. Return Value:
  2007. None.
  2008. --*/
  2009. PTYPEINFOELEMENT pNext;
  2010. while(NULL != pThis) {
  2011. pNext = pThis->pNext;
  2012. if (pThis->pTypeInfo != NULL) GenHeapFree(pThis->pTypeInfo);
  2013. GenHeapFree(pThis);
  2014. pThis = pNext;
  2015. }
  2016. }
  2017. VOID
  2018. GenerateProxy(
  2019. char *pName,
  2020. PTYPESINFO pTypesInfo
  2021. )
  2022. {
  2023. /*++
  2024. Routine Description:
  2025. Generates proxy infomation for functions in a struct with virtual methods.
  2026. The infomation is of the form structname_functionname_Proxy.
  2027. The function is added to the functions list if not already in the list.
  2028. The discardable flag is set so that this type will be redefined in refound in the code.
  2029. Arguments:
  2030. pName -- [IN] ptr to the name of the struct that the method is in.
  2031. pTypesInfo -- [IN] Information for the function.
  2032. Return Value:
  2033. None.
  2034. --*/
  2035. TYPESINFO NewTypesInfo;
  2036. PFUNCINFO pFuncInfo;
  2037. PFUNCINFO *ppFuncInfo;
  2038. PFUNCINFO pCurrent;
  2039. BUFALLOCINFO bufallocinfo;
  2040. char *pChar;
  2041. DWORD dwSizeArgName, dwSizeTypeName;
  2042. // Bail out if not func, no struct name, or no class name
  2043. if (pName == NULL || pTypesInfo->TypeName == NULL) return;
  2044. if (pTypesInfo->TypeKind != TypeKindFunc ||
  2045. strlen(pName) == 0 ||
  2046. strlen(pTypesInfo->TypeName) == 0) return;
  2047. NewTypesInfo = *pTypesInfo;
  2048. strcpy(NewTypesInfo.TypeName, pName);
  2049. strcat(NewTypesInfo.TypeName, "_");
  2050. strcat(NewTypesInfo.TypeName, pTypesInfo->TypeName);
  2051. strcat(NewTypesInfo.TypeName, "_Proxy");
  2052. /////////////////////////////////////////////////////////////////
  2053. //Check if the function has already been added.
  2054. //If it has, no more work is needed.
  2055. /////////////////////////////////////////////////////////////////
  2056. if (GetNameFromTypesList(FuncsList, NewTypesInfo.TypeName) != NULL)
  2057. return;
  2058. ////////////////////////////////////////////////////////////////////
  2059. //Copy function members adding a this pointer at head
  2060. //and skipping void arguments.
  2061. ////////////////////////////////////////////////////////////////////
  2062. BufAllocInit(&bufallocinfo, NewTypesInfo.Members, FUNCMEMBERSIZE, 0);
  2063. dwSizeTypeName = strlen(pName) + 1;
  2064. dwSizeArgName = strlen(szThis) + 1;
  2065. pFuncInfo = (PFUNCINFO)BufAllocate(&bufallocinfo, sizeof(FUNCINFO) + dwSizeArgName + dwSizeTypeName);
  2066. if (NULL == pFuncInfo) ExitErrMsg(FALSE, "Out of buffer memory! %d", __LINE__);
  2067. pFuncInfo->fIsPtr64 = FALSE;
  2068. pFuncInfo->tkDirection = TK_IN;
  2069. pFuncInfo->tkPreMod = TK_NONE;
  2070. pFuncInfo->tkSUE = TK_NONE;
  2071. pFuncInfo->tkPrePostMod = TK_NONE;
  2072. pFuncInfo->IndLevel = 1;
  2073. pFuncInfo->tkPostMod = TK_NONE;
  2074. pChar = ((char *)pFuncInfo) + sizeof(FUNCINFO);
  2075. strcpy(pChar, pName);
  2076. pFuncInfo->sType = pChar;
  2077. pChar += dwSizeTypeName;
  2078. strcpy(pChar, szThis);
  2079. pFuncInfo->sName = pChar;
  2080. pFuncInfo->pfuncinfoNext = NULL;
  2081. NewTypesInfo.pfuncinfo = pFuncInfo;
  2082. ppFuncInfo = &(pFuncInfo->pfuncinfoNext);
  2083. //skip an argument of type void if it is at the begining.
  2084. //This is needed since ParseFuncTypes puts a void arg if the
  2085. //func does not have any arguments
  2086. pCurrent = pTypesInfo->pfuncinfo;
  2087. if (pCurrent != NULL &&
  2088. strcmp(szVOID, pCurrent->sType) == 0
  2089. && pCurrent->IndLevel == 0) {
  2090. pCurrent = pCurrent->pfuncinfoNext;
  2091. }
  2092. for(; pCurrent != NULL; pCurrent=pCurrent->pfuncinfoNext) {
  2093. dwSizeTypeName = strlen(pCurrent->sType) + 1;
  2094. dwSizeArgName = strlen(pCurrent->sName) + 1;
  2095. pFuncInfo = (PFUNCINFO)BufAllocate(&bufallocinfo, sizeof(FUNCINFO) + dwSizeArgName + dwSizeTypeName);
  2096. if (NULL == pFuncInfo) ExitErrMsg(FALSE, "Out of buffer memory! %d", __LINE__);
  2097. *pFuncInfo = *pCurrent;
  2098. pChar = ((char *)pFuncInfo) + sizeof(FUNCINFO);
  2099. strcpy(pChar, pCurrent->sType);
  2100. pFuncInfo->sType = pChar;
  2101. pChar += dwSizeTypeName;
  2102. strcpy(pChar, pCurrent->sName);
  2103. pFuncInfo->sName = pChar;
  2104. pFuncInfo->pfuncinfoNext = NULL;
  2105. *ppFuncInfo = pFuncInfo;
  2106. ppFuncInfo = &(pFuncInfo->pfuncinfoNext);
  2107. }
  2108. NewTypesInfo.Flags |= BTI_DISCARDABLE;
  2109. NewTypesInfo.dwMemberSize = bufallocinfo.dwLen;
  2110. if (!AddNewType(&NewTypesInfo, FuncsList))
  2111. ExitErrMsg(FALSE, "Unable to add proxy information.(Type was not in list)\n");
  2112. }
  2113. BOOL
  2114. CopyStructMembers(
  2115. PTYPESINFO pTypesInfo,
  2116. BOOL bUnion,
  2117. PKNOWNTYPES pBaseType
  2118. )
  2119. {
  2120. /*++
  2121. Routine Description:
  2122. Parses the members of the structure and adds them to the pTypesInfo.
  2123. Handles merging of members and methods when the structure is derived
  2124. from another structure. Delegates actual parsing to pCopyStructMembers.
  2125. Arguments:
  2126. pTypesInfo -- [IN OUT] ptr to infomation for the type being processed.
  2127. dwElemSize -- [IN] TRUE if processing a union, FALSE if a struct.
  2128. bUnion -- [IN] ptr to KNOWNTYPE of base structure or NULL.
  2129. Return Value:
  2130. TRUE - If success.
  2131. --*/
  2132. PTYPEINFOELEMENT pMemberFuncs = NULL;
  2133. char *VTBLFakeMember;
  2134. PMEMBERINFO pHead = NULL; //Head in final merge
  2135. PMEMBERINFO pTail = NULL; //Tail in final merge
  2136. DWORD dwiPackSize; //For tail
  2137. DWORD dwSize; //For tail
  2138. DWORD dwOffset; //For tail
  2139. BUFALLOCINFO bufallocinfo;
  2140. dwScopeLevel++;
  2141. /////////////////////////////////////////////////////////////////
  2142. //Add a discardable version of this struct if one doesn't exist
  2143. /////////////////////////////////////////////////////////////////
  2144. if (GetNameFromTypesList(StructsList, pTypesInfo->TypeName) == NULL) {
  2145. TYPESINFO TTypesInfo;
  2146. TTypesInfo = *pTypesInfo;
  2147. TTypesInfo.Flags |= BTI_DISCARDABLE;
  2148. AddNewType(&TTypesInfo, StructsList); //intentionally do not check
  2149. }
  2150. if(bUnion) return pCopyStructMembers(pTypesInfo, bUnion, NULL, 0, 0);
  2151. if (pBaseType == NULL) {
  2152. if (!pCopyStructMembers(pTypesInfo, FALSE, &pMemberFuncs, 0, 0)) {
  2153. FreeTypeInfoList(pMemberFuncs);
  2154. return FALSE;
  2155. }
  2156. if (pMemberFuncs!=NULL && pTypesInfo->Size > 0) {
  2157. ErrMsg("Error: struct %s mixes data members and virtual functions(sortpp limitation).\n", pTypesInfo->TypeName);
  2158. FreeTypeInfoList(pMemberFuncs);
  2159. return FALSE;
  2160. }
  2161. pTypesInfo->dwVTBLSize = 0;
  2162. pTypesInfo->dwVTBLOffset = 0;
  2163. if (pMemberFuncs != NULL) {
  2164. PTYPEINFOELEMENT pThisElement;
  2165. DWORD dwElements = 0;
  2166. DWORD dwLength, dwVoidLen, dwVTBLLen;
  2167. PMEMBERINFO pMemberInfo;
  2168. char *pName;
  2169. ///////////////////////////////////////////////////////////////////////////
  2170. //Build the fake VTBL pointer
  2171. /////////////////////////////////////////////////////////////////////////////
  2172. //Add the VTBL member
  2173. dwVoidLen = strlen(szVOID) + 1;
  2174. dwVTBLLen = strlen(szVTBL) + 1;
  2175. memset(pTypesInfo->Members, 0, FUNCMEMBERSIZE);
  2176. BufAllocInit(&bufallocinfo, pTypesInfo->Members, FUNCMEMBERSIZE, 0);
  2177. pMemberInfo = (PMEMBERINFO)BufAllocate(&bufallocinfo, sizeof(MEMBERINFO) + dwVoidLen + dwVTBLLen);
  2178. if (NULL == pMemberInfo) ExitErrMsg(FALSE, "Out of buffer memory! %d", __LINE__);
  2179. pName = ((char *)pMemberInfo) + sizeof(MEMBERINFO);
  2180. strcpy(pName, szVTBL);
  2181. pMemberInfo->sName = pName;
  2182. pName += dwVTBLLen;
  2183. strcpy(pName, szVOID);
  2184. pMemberInfo->sType = pName;
  2185. pMemberInfo->pmeminfoNext = NULL;
  2186. pMemberInfo->dwOffset = 0;
  2187. pMemberInfo->IndLevel = 1;
  2188. pMemberInfo->pktCache = 0;
  2189. pTypesInfo->iPackSize = PackCurrentPacking() < SIZEOFPOINTER ?
  2190. PackCurrentPacking() : SIZEOFPOINTER;
  2191. pTypesInfo->Size = SIZEOFPOINTER;
  2192. pTypesInfo->dwMemberSize = bufallocinfo.dwLen;
  2193. pTypesInfo->Flags |= BTI_VIRTUALONLY;
  2194. ///////////////////////////////////////////////////////////////////////////////
  2195. //Build the list of functions in the VTBL
  2196. ///////////////////////////////////////////////////////////////////////////////
  2197. //copy methods over to Methods and IMethods
  2198. for(pThisElement = pMemberFuncs; pThisElement != NULL; pThisElement = pThisElement->pNext) {
  2199. if(pThisElement->pTypeInfo != NULL) {
  2200. if(!AppendToMultiSz(pTypesInfo->Methods, pThisElement->pTypeInfo->TypeName, MEMBERMETHODSSIZE) ||
  2201. !AppendToMultiSz(pTypesInfo->IMethods, pThisElement->pTypeInfo->TypeName, MEMBERMETHODSSIZE)) {
  2202. ExitErrMsg(FALSE,"Too many methods in %s\n", pTypesInfo->TypeName);
  2203. }
  2204. GenerateProxy(pTypesInfo->TypeName, pThisElement->pTypeInfo);
  2205. dwElements++;
  2206. }
  2207. }
  2208. pTypesInfo->dwVTBLSize = dwElements;
  2209. pTypesInfo->dwVTBLOffset = 0;
  2210. //If this is IUnknown, it is a COM object
  2211. if (strcmp("IUnknown", pTypesInfo->TypeName) == 0)
  2212. pTypesInfo->Flags |= BTI_ISCOM;
  2213. }
  2214. }
  2215. else {
  2216. if(!pCopyStructMembers(pTypesInfo, FALSE, &pMemberFuncs, pBaseType->Size, pBaseType->iPackSize)) {
  2217. FreeTypeInfoList(pMemberFuncs);
  2218. return FALSE;
  2219. }
  2220. // This checks that structures with data member are not mixed with structures with virtual methods.
  2221. // This is a sortpp limitation that makes computing the packing size during inheritance easier.
  2222. // The if statement say that a valid inheritance is either.
  2223. // 1. The derived class does not add new virtual methods or data members.
  2224. // 2. The derived class does not add new virtual methods, adds no new data members, and it inherites from a class with no virtual functions.
  2225. // 3. The derived class adds virtual functions, adds no new data members, and the base class has no data members.
  2226. if (!((pMemberFuncs == NULL && pTypesInfo->dwMemberSize == 0) ||
  2227. (pMemberFuncs == NULL && pTypesInfo->dwMemberSize > 0 && pBaseType->dwVTBLSize == 0) ||
  2228. (pMemberFuncs != NULL && pTypesInfo->dwMemberSize == 0 && pBaseType->SizeMembers == 0)
  2229. )) {
  2230. ErrMsg("Error: struct %s mixes data members and virtual functions(sortpp limitation).\n", pTypesInfo->TypeName);
  2231. ErrMsg("pMemberFuncs %p\n pTypesInfo->dwMemberSize %x\n pBaseType->Flags %x\n pBaseType->pmeminfo %p\n",
  2232. pMemberFuncs,
  2233. pTypesInfo->dwMemberSize,
  2234. pBaseType->Flags,
  2235. pBaseType->pmeminfo);
  2236. FreeTypeInfoList(pMemberFuncs);
  2237. return FALSE;
  2238. }
  2239. pTypesInfo->dwVTBLSize = pTypesInfo->dwVTBLOffset = pBaseType->dwVTBLSize;
  2240. pTypesInfo->Flags |= (pBaseType->Flags & ~BTI_HASGUID);
  2241. if(pMemberFuncs == NULL) {
  2242. char *Members;
  2243. PMEMBERINFO pHead, pTail, pTemp;
  2244. if (pBaseType->pmeminfo != NULL)
  2245. pHead = (PMEMBERINFO)pBaseType->pmeminfo;
  2246. else
  2247. pHead = NULL;
  2248. if (pTypesInfo->dwMemberSize > 0)
  2249. pTail = (PMEMBERINFO)pTypesInfo->Members;
  2250. else
  2251. pTail = NULL;
  2252. /////////////////////////////////////////////////////////////////////////////
  2253. //Allocate memory for the temp array
  2254. /////////////////////////////////////////////////////////////////////////////
  2255. Members = GenHeapAlloc(FUNCMEMBERSIZE);
  2256. if (Members == NULL)
  2257. ExitErrMsg(FALSE, "Out of memory!\n");
  2258. /////////////////////////////////////////////////////////////////////////////
  2259. //merge members lists with basetype
  2260. /////////////////////////////////////////////////////////////////////////////
  2261. //copy the concatination of the two to the temp buffer
  2262. BufAllocInit(&bufallocinfo, Members, FUNCMEMBERSIZE, 0);
  2263. pTemp = CatMeminfo(&bufallocinfo, pHead, pTail, 0, FALSE);
  2264. ////////////////////////////////////////////////////////////////////////
  2265. //copy members from temp buffers back to pTypesInfo
  2266. ////////////////////////////////////////////////////////////////////////
  2267. memset( pTypesInfo->Members, 0, FUNCMEMBERSIZE );
  2268. BufAllocInit(&bufallocinfo, pTypesInfo->Members, FUNCMEMBERSIZE, 0);
  2269. if (pTemp) {
  2270. // Only call this one if the first one did anyting. Otherwise
  2271. // This one reads from uninitialized heap.
  2272. CatMeminfo(&bufallocinfo, (PMEMBERINFO)Members, NULL, 0, FALSE);
  2273. }
  2274. pTypesInfo->dwMemberSize = bufallocinfo.dwLen;
  2275. GlobalFree(Members);
  2276. }
  2277. else {
  2278. PTYPEINFOELEMENT pThisElement;
  2279. DWORD dwElements = 0;
  2280. // This struct is virtual only since methods are being added. We already checked that no
  2281. // data members will be in the structure.
  2282. pTypesInfo->Flags |= BTI_VIRTUALONLY;
  2283. ////////////////////////////////////////////////////////
  2284. //Copy base members over
  2285. ////////////////////////////////////////////////////////
  2286. memset( pTypesInfo->Members, 0, FUNCMEMBERSIZE );
  2287. BufAllocInit(&bufallocinfo, pTypesInfo->Members, FUNCMEMBERSIZE, 0);
  2288. CatMeminfo(&bufallocinfo, pBaseType->pmeminfo, NULL, 0, FALSE);
  2289. pTypesInfo->dwMemberSize = bufallocinfo.dwLen;
  2290. ///////////////////////////////////////////////////////////////////////////////
  2291. //Build the list of functions in the VTBL
  2292. ///////////////////////////////////////////////////////////////////////////////
  2293. //copy unique methods over to IMethods
  2294. for(pThisElement = pMemberFuncs; pThisElement != NULL; pThisElement = pThisElement->pNext) {
  2295. if(pThisElement->pTypeInfo != NULL) {
  2296. if (!IsInMultiSz(pBaseType->Methods, pThisElement->pTypeInfo->TypeName)) {
  2297. if(!AppendToMultiSz(pTypesInfo->IMethods, pThisElement->pTypeInfo->TypeName,
  2298. MEMBERMETHODSSIZE)) {
  2299. ExitErrMsg(FALSE,"Too many methods in %s\n", pTypesInfo->TypeName);
  2300. }
  2301. GenerateProxy(pTypesInfo->TypeName, pThisElement->pTypeInfo);
  2302. dwElements++;
  2303. }
  2304. }
  2305. }
  2306. memcpy(pTypesInfo->Methods, pBaseType->Methods, SizeOfMultiSz(pBaseType->Methods));
  2307. if (!CatMultiSz(pTypesInfo->Methods, pTypesInfo->IMethods, MEMBERMETHODSSIZE))
  2308. ExitErrMsg(FALSE, "Too many methods in %s\n", pTypesInfo->TypeName);
  2309. pTypesInfo->dwVTBLSize = dwElements + pBaseType->dwVTBLSize;
  2310. pTypesInfo->dwVTBLOffset = pBaseType->dwVTBLSize;
  2311. }
  2312. }
  2313. FreeTypeInfoList(pMemberFuncs);
  2314. return TRUE;
  2315. }
  2316. void
  2317. BumpStructUnionSize(
  2318. DWORD *pdwSize,
  2319. DWORD dwElemSize,
  2320. BOOL bUnion
  2321. )
  2322. /*++
  2323. Routine Description:
  2324. Updates overall size of a struct/union
  2325. Arguments:
  2326. pdwSize -- [IN OUT] overall size of struct/union
  2327. dwElemSize -- size of new element to add into the struct/union
  2328. bUnion -- TRUE if a union, FALSE if a struct
  2329. Return Value:
  2330. None.
  2331. --*/
  2332. {
  2333. if (bUnion) {
  2334. //
  2335. // Size of a union is max(dwSize, dwElementSize)
  2336. //
  2337. if (dwElemSize > *pdwSize) {
  2338. *pdwSize = dwElemSize;
  2339. }
  2340. } else {
  2341. //
  2342. // Size of a struct is current size of struct plus element size
  2343. //
  2344. *pdwSize = *pdwSize + dwElemSize;
  2345. }
  2346. }
  2347. BOOL
  2348. ParseGuid(
  2349. GUID *pGuid
  2350. )
  2351. {
  2352. /*++
  2353. Routine Description:
  2354. Parses a guid of the type found in a variable declaration.
  2355. Arguments:
  2356. pGuid - [OUT] ptr to the guid.
  2357. Return Value:
  2358. TRUE - Guid parsed.
  2359. FALSE - Parse failed.
  2360. --*/
  2361. unsigned int c;
  2362. LONGLONG value;
  2363. if (CurrentToken()->TokenType != TK_LBRACE) return FALSE;
  2364. ConsumeToken();
  2365. if (CurrentToken()->TokenType != TK_NUMBER) return FALSE;
  2366. value = expr();
  2367. if (value < 0 || value > 0xFFFFFFFF) return FALSE;
  2368. pGuid->Data1 = (unsigned long)value;
  2369. if (CurrentToken()->TokenType != TK_COMMA) return FALSE;
  2370. ConsumeToken();
  2371. if (CurrentToken()->TokenType != TK_NUMBER) return FALSE;
  2372. value = expr();
  2373. if (value < 0 || value > 0xFFFF) return FALSE;
  2374. pGuid->Data2 = (unsigned short)value;
  2375. if (CurrentToken()->TokenType != TK_COMMA) return FALSE;
  2376. ConsumeToken();
  2377. if (CurrentToken()->TokenType != TK_NUMBER) return FALSE;
  2378. value = expr();
  2379. if (value < 0 || value > 0xFFFF) return FALSE;
  2380. pGuid->Data2 = (unsigned short)value;
  2381. if (CurrentToken()->TokenType != TK_COMMA) return FALSE;
  2382. ConsumeToken();
  2383. if (CurrentToken()->TokenType != TK_LBRACE) return FALSE;
  2384. ConsumeToken();
  2385. c = 0;
  2386. while(TRUE) {
  2387. if (CurrentToken()->TokenType != TK_NUMBER) return FALSE;
  2388. value = expr();
  2389. if(value < 0 || value > 0xFF) return FALSE;
  2390. pGuid->Data4[c] = (unsigned char)value;
  2391. if (7 == c) break;
  2392. if (CurrentToken()->TokenType != TK_COMMA) return FALSE;
  2393. ConsumeToken();
  2394. c++;
  2395. }
  2396. for(c=0; c<2; c++) {
  2397. if (CurrentToken()->TokenType != TK_RBRACE) return FALSE;
  2398. ConsumeToken();
  2399. }
  2400. return TRUE;
  2401. }
  2402. BOOL
  2403. ParseVariables(
  2404. VOID
  2405. )
  2406. {
  2407. /*++
  2408. Routine Description:
  2409. Attempts to parse a variable declaration. If successful, the variable
  2410. is added to the variable list.
  2411. Arguments:
  2412. none
  2413. Return Value:
  2414. TRUE - If success.
  2415. --*/
  2416. TYPESINFO TypesInfo;
  2417. GUID Guid;
  2418. char *Name;
  2419. ConsumeConstVolatileOpt();
  2420. if (!GetExistingType(&TypesInfo, NULL, NULL)) return FALSE;
  2421. while(CurrentToken()->TokenType == TK_STAR) ConsumeToken();
  2422. if (CurrentToken()->TokenType == TK_DECLSPEC) {
  2423. ConsumeDeclSpecOpt(FALSE, FALSE, NULL, NULL, NULL);
  2424. }
  2425. //next token should be the variable name
  2426. if (CurrentToken()->TokenType != TK_IDENTIFIER) return FALSE;
  2427. Name = CurrentToken()->Name;
  2428. ConsumeToken();
  2429. if (CurrentToken()->TokenType == TK_EOS) return AddVariable(Name, NULL);
  2430. if (CurrentToken()->TokenType != TK_ASSIGN) return FALSE;
  2431. ConsumeToken();
  2432. if (CurrentToken()->TokenType == TK_NUMBER || CurrentToken()->TokenType == TK_STRING) {
  2433. ConsumeToken();
  2434. if (CurrentToken()->TokenType == TK_EOS) return AddVariable(Name, NULL);
  2435. return FALSE;
  2436. }
  2437. else if (CurrentToken()->TokenType == TK_LBRACE) {
  2438. //attempt to parse a guid definition
  2439. if (ParseGuid(&Guid) &&
  2440. CurrentToken()->TokenType == TK_EOS) return AddVariable(Name, &Guid);
  2441. else return FALSE;
  2442. }
  2443. else return FALSE;
  2444. }
  2445. BOOL
  2446. GetArrayIndex(
  2447. DWORD *pdw
  2448. )
  2449. /*++
  2450. Routine Description:
  2451. Parses the size of an array index by evaluating a C-language constant
  2452. expression.
  2453. Arguments:
  2454. pdw -- [OUT] ptr to size of the array index.
  2455. Return Value:
  2456. TRUE if array index parsed (CurrentToken points after the ']')
  2457. FALSE if parse failed.
  2458. --*/
  2459. {
  2460. LONGLONG value;
  2461. *pdw = 0; // assume no size
  2462. if (CurrentToken()->TokenType != TK_LSQUARE) {
  2463. return FALSE;
  2464. }
  2465. ConsumeToken();
  2466. value = expr();
  2467. if (value < 0 || value > 0xFFFFFFFF) return FALSE;
  2468. *pdw = (DWORD)value;
  2469. if (CurrentToken()->TokenType != TK_RSQUARE) {
  2470. return FALSE;
  2471. }
  2472. ConsumeToken();
  2473. return TRUE;
  2474. }
  2475. LONGLONG
  2476. expr(
  2477. void
  2478. )
  2479. {
  2480. LONGLONG val = expr_a1();
  2481. while(1) {
  2482. switch (CurrentToken()->TokenType) {
  2483. case TK_BITWISE_AND:
  2484. ConsumeToken();
  2485. val &= expr_a1();
  2486. break;
  2487. case TK_BITWISE_OR:
  2488. ConsumeToken();
  2489. val |= expr_a1();
  2490. break;
  2491. default:
  2492. return val;
  2493. }
  2494. } while (1);
  2495. }
  2496. LONGLONG
  2497. expr_a1(
  2498. void
  2499. )
  2500. {
  2501. LONGLONG val = expr_a();
  2502. while(1) {
  2503. switch (CurrentToken()->TokenType) {
  2504. case TK_LSHIFT:
  2505. ConsumeToken();
  2506. val <<= expr_a();
  2507. break;
  2508. case TK_RSHIFT:
  2509. ConsumeToken();
  2510. val >>= expr_a();
  2511. break;
  2512. default:
  2513. return val;
  2514. }
  2515. }
  2516. }
  2517. LONGLONG
  2518. expr_a(
  2519. void
  2520. )
  2521. /*++
  2522. Routine Description:
  2523. Parses a C-language constant expression and returns the value - handles
  2524. the operators 'plus' and 'minus'.
  2525. Arguments:
  2526. None.
  2527. Return Value:
  2528. Value of the expression.
  2529. --*/
  2530. {
  2531. LONGLONG val = expr_b();
  2532. do
  2533. {
  2534. switch (CurrentToken()->TokenType) {
  2535. case TK_PLUS:
  2536. ConsumeToken();
  2537. val += expr_b();
  2538. break;
  2539. case TK_MINUS:
  2540. ConsumeToken();
  2541. val -= expr_b();
  2542. break;
  2543. default:
  2544. return val;
  2545. }
  2546. } while (1);
  2547. }
  2548. LONGLONG
  2549. expr_b(
  2550. void
  2551. )
  2552. /*++
  2553. Routine Description:
  2554. Part of expression evaluator - handles the highest-precedence operators
  2555. 'multiply' and 'divide'.
  2556. Arguments:
  2557. None.
  2558. Return Value:
  2559. Value of the expression.
  2560. --*/
  2561. {
  2562. LONGLONG val = expr_c();
  2563. do
  2564. {
  2565. switch (CurrentToken()->TokenType) {
  2566. case TK_STAR:
  2567. ConsumeToken();
  2568. val *= expr_c();
  2569. break;
  2570. case TK_DIVIDE:
  2571. ConsumeToken();
  2572. val /= expr_c();
  2573. break;
  2574. case TK_MOD:
  2575. ConsumeToken();
  2576. val %= expr_c();
  2577. break;
  2578. default:
  2579. // done
  2580. return val;
  2581. }
  2582. } while (1);
  2583. }
  2584. LONGLONG
  2585. expr_c(
  2586. void
  2587. )
  2588. /*++
  2589. Routine Description:
  2590. Part of expression evaluator - handles unary parts of the expression, like
  2591. numbers, unary minus, and parentheses.
  2592. Arguments:
  2593. None.
  2594. Return Value:
  2595. Value of the expression.
  2596. --*/
  2597. {
  2598. LONGLONG val;
  2599. PKNOWNTYPES pkt;
  2600. switch (CurrentToken()->TokenType) {
  2601. case TK_NUMBER:
  2602. val = CurrentToken()->dwValue;
  2603. ConsumeToken();
  2604. break;
  2605. case TK_MINUS: // unary minus
  2606. ConsumeToken();
  2607. val = -expr_c();
  2608. break;
  2609. case TK_TILDE: // unary not
  2610. ConsumeToken();
  2611. val = ~expr_c();
  2612. break;
  2613. case TK_LPAREN:
  2614. ConsumeToken();
  2615. val = expr();
  2616. if (CurrentToken()->TokenType != TK_RPAREN) {
  2617. ErrMsg("Syntax error: expected ')'");
  2618. }
  2619. ConsumeToken();
  2620. break;
  2621. case TK_RSQUARE:
  2622. val = 0;
  2623. break;
  2624. case TK_SIZEOF:
  2625. ConsumeToken(); // eat the sizeof keyword
  2626. if (CurrentToken()->TokenType != TK_LPAREN) {
  2627. ErrMsg("Expected '(' after 'sizeof\n");
  2628. val = 0;
  2629. break;
  2630. }
  2631. ConsumeToken(); // eat the '('
  2632. if (CurrentToken()->TokenType == TK_STRING) {
  2633. // sizeof(string literal)
  2634. val = strlen(CurrentToken()->Name) + 1;
  2635. ConsumeToken();
  2636. } else {
  2637. // sizeof(some type)
  2638. TYPESINFO TypesInfo;
  2639. DWORD dwIndLevel;
  2640. DWORD dwSize;
  2641. if (!GetExistingType(&TypesInfo, NULL, NULL)) {
  2642. ExitErrMsg(FALSE, "Parse error in sizeof(typename)\n");
  2643. }
  2644. dwIndLevel = 0;
  2645. ParseIndirection(&dwIndLevel, &dwSize, NULL, NULL, NULL);
  2646. if (dwIndLevel) {
  2647. val = (int)dwSize;
  2648. } else {
  2649. val = TypesInfo.Size;
  2650. }
  2651. }
  2652. if (CurrentToken()->TokenType != TK_RPAREN) {
  2653. ErrMsg("Expected ')' after 'sizeof(expr)\n");
  2654. val = 0;
  2655. break;
  2656. }
  2657. ConsumeToken(); // eat the ')'
  2658. break;
  2659. default:
  2660. ErrMsg("Syntax error parsing expression\n");
  2661. val = 0;
  2662. break;
  2663. }
  2664. return val;
  2665. }
  2666. int
  2667. CreatePseudoName(
  2668. char *pDst,
  2669. char *pSrc
  2670. )
  2671. /*++
  2672. Routine Description:
  2673. Prefixes a given name with an index number and copies it into a buffer.
  2674. Arguments:
  2675. pDst -- [OUT] destination for the new name
  2676. pSrc -- [IN] source for the base name (may be same as pDst)
  2677. Return Value:
  2678. Chars copied, 0 for failure.
  2679. --*/
  2680. {
  2681. static PseudoNameIndex = 0;
  2682. int Len;
  2683. char Buffer[MAX_PATH];
  2684. Len = _snprintf(Buffer,
  2685. sizeof(Buffer) - 1,
  2686. "__wx86%2.2d%s",
  2687. PseudoNameIndex++,
  2688. pSrc
  2689. );
  2690. if (Len <= 0) {
  2691. ErrMsg("cpn: buffer overflow <%s>\n", pSrc);
  2692. return 0;
  2693. }
  2694. strcpy(pDst, Buffer);
  2695. return Len;
  2696. }
  2697. void
  2698. PackPush(
  2699. char *sIdentifier
  2700. )
  2701. /*++
  2702. Routine Description:
  2703. Handles '#pragma pack (push...)'
  2704. Arguments:
  2705. sIdentifier -- [OPTIONAL] name to associate with the current pack level
  2706. Return Value:
  2707. None. Pack-stack updated.
  2708. --*/
  2709. {
  2710. PACKHOLDER *ppackholder;
  2711. if (!sIdentifier) {
  2712. sIdentifier = "";
  2713. }
  2714. DbgPrintf("push (%d)\n", PackCurrentPacking());
  2715. ppackholder = GenHeapAlloc(sizeof(PACKHOLDER) + strlen(sIdentifier));
  2716. if (ppackholder == NULL) {
  2717. ExitErrMsg(FALSE, "Out of memory for packing stack");
  2718. }
  2719. ppackholder->dwPacking = PackCurrentPacking();
  2720. ppackholder->ppackholderNext = ppackholderHead;
  2721. strcpy(ppackholder->sIdentifier, sIdentifier);
  2722. ppackholderHead = ppackholder;
  2723. }
  2724. DWORD
  2725. PackPop(
  2726. char *sIdentifier
  2727. )
  2728. /*++
  2729. Routine Description:
  2730. Handles '#pragma pack (pop...)'
  2731. Arguments:
  2732. sIdentifier -- [OPTIONAL] name to pop to
  2733. Return Value:
  2734. Returns new packing value. Pack-stack updated.
  2735. --*/
  2736. {
  2737. PACKHOLDER *ppackholder;
  2738. PACKHOLDER *ppackholderPop;
  2739. PACKHOLDER *ppackholderNext;
  2740. DWORD dw = DEFAULTPACKINGSIZE;
  2741. if (ppackholderHead == NULL) {
  2742. ExitErrMsg(FALSE, "Error: '#pragma pack' stack underflow.");
  2743. }
  2744. if (sIdentifier == NULL) {
  2745. ppackholder = ppackholderHead;
  2746. ppackholderHead = ppackholder->ppackholderNext;
  2747. dw = ppackholder->dwPacking;
  2748. GenHeapFree(ppackholder);
  2749. } else {
  2750. ppackholderPop = ppackholderHead;
  2751. do {
  2752. DbgPrintf("Poping for %s [%s]\n", sIdentifier, ppackholderPop ? ppackholderPop->sIdentifier : "-");
  2753. ppackholderNext = ppackholderPop->ppackholderNext;
  2754. if (strcmp(sIdentifier, ppackholderPop->sIdentifier) == 0) {
  2755. dw = ppackholderPop->dwPacking;
  2756. break;
  2757. }
  2758. ppackholderPop = ppackholderNext;
  2759. } while (ppackholderPop != NULL);
  2760. DbgPrintf("Found %s\n", ppackholderPop ? ppackholderPop->sIdentifier : "-");
  2761. if (ppackholderPop != NULL) {
  2762. ppackholderNext = ppackholderHead;
  2763. do {
  2764. ppackholder = ppackholderNext;
  2765. ppackholderNext = ppackholder->ppackholderNext;
  2766. ppackholderHead = ppackholderNext;
  2767. GenHeapFree(ppackholder);
  2768. } while (ppackholder != ppackholderPop);
  2769. }
  2770. }
  2771. DbgPrintf("pop (%d)\n", dw);
  2772. return(dw);
  2773. }
  2774. BOOL
  2775. PrepareMappedMemory(
  2776. void
  2777. )
  2778. /*++
  2779. Routine Description:
  2780. Creates the memory for the .PPM file.
  2781. Arguments:
  2782. None.
  2783. Return Value:
  2784. TRUE on success, FALSE on failure.
  2785. --*/
  2786. {
  2787. PCVMHEAPHEADER pHeader;
  2788. hCvmHeap = CreateAllocCvmHeap(uBaseAddress, // uBaseAddress
  2789. uReserveSize, // uReservedSize
  2790. 0x00010000, // uRegionSize
  2791. 0, // uUncommited
  2792. 0, // uUnReserved
  2793. 0); // uAvailable
  2794. if (hCvmHeap != NULL) {
  2795. // create the heap header
  2796. pHeader = SortppAllocCvm(sizeof(CVMHEAPHEADER));
  2797. if (!pHeader) {
  2798. return FALSE;
  2799. }
  2800. pHeader->Version = VM_TOOL_VERSION;
  2801. pHeader->BaseAddress = (ULONG_PTR)GetCvmHeapBaseAddress(hCvmHeap);
  2802. fpTypesListMalloc = SortppAllocCvm;
  2803. FuncsList = &pHeader->FuncsList;
  2804. StructsList = &pHeader->StructsList;
  2805. TypeDefsList = &pHeader->TypeDefsList;
  2806. NIL = &pHeader->NIL;
  2807. }
  2808. return(hCvmHeap != NULL);
  2809. }
  2810. PVOID
  2811. SortppAllocCvm(
  2812. ULONG Size
  2813. )
  2814. /*++
  2815. Routine Description:
  2816. Allocates memory from the .PPM file mapping.
  2817. Arguments:
  2818. None.
  2819. Return Value:
  2820. ptr to new memory, or NULL on failure.
  2821. --*/
  2822. {
  2823. return AllocCvm(hCvmHeap, Size);
  2824. }
  2825. BOOL
  2826. WritePpmFile(
  2827. char *PpmName
  2828. )
  2829. /*++
  2830. Routine Description:
  2831. Write the .PPM file out to disk.
  2832. Arguments:
  2833. Ppmname -- [IN] name for .PPM file
  2834. Return Value:
  2835. TRUE on success, FALSE on failure.
  2836. --*/
  2837. {
  2838. NTSTATUS Status;
  2839. BOOL bSuccess;
  2840. HANDLE hPpmFile;
  2841. DWORD BytesWritten;
  2842. ULONG_PTR uBaseAddress = (ULONG_PTR)GetCvmHeapBaseAddress(hCvmHeap);
  2843. ULONG_PTR uAvailable = (ULONG_PTR)GetCvmHeapAvailable(hCvmHeap);
  2844. hPpmFile = CreateFile(PpmName,
  2845. GENERIC_WRITE,
  2846. 0,
  2847. NULL,
  2848. CREATE_ALWAYS,
  2849. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  2850. NULL
  2851. );
  2852. if (hPpmFile == INVALID_HANDLE_VALUE) {
  2853. ExitErrMsg(FALSE,
  2854. "CreateFile(%s) failed %x\n",
  2855. PpmName,
  2856. GetLastError()
  2857. );
  2858. }
  2859. if (!AddOpenFile(PpmName, 0, hPpmFile)) {
  2860. ExitErrMsg(FALSE, "AddOpenFile failed\n");
  2861. }
  2862. #if _WIN64
  2863. if ((uAvailable - uBaseAddress) > MAXHALF_PTR) {
  2864. ExitErrMsg(FALSE, "Attempt to write more than 0x%x bytes not allowed\n", MAXHALF_PTR);
  2865. }
  2866. #endif
  2867. bSuccess = WriteFile(hPpmFile,
  2868. (PVOID)uBaseAddress,
  2869. (DWORD)(uAvailable - uBaseAddress),
  2870. &BytesWritten,
  2871. NULL
  2872. );
  2873. if (!bSuccess || BytesWritten != uAvailable - uBaseAddress) {
  2874. ExitErrMsg(FALSE,
  2875. "WriteFile(%s) failed %x\n",
  2876. PpmName,
  2877. GetLastError()
  2878. );
  2879. }
  2880. DelOpenFile(0, hPpmFile);
  2881. CloseHandle(hPpmFile);
  2882. return TRUE;
  2883. }
  2884. void
  2885. HandlePreprocessorDirective(
  2886. char *Line
  2887. )
  2888. /*++
  2889. Routine Description:
  2890. Scan and process a '#' preprocessor directive.
  2891. Accepts:
  2892. #pragma line LINENUM SOURCEFILE
  2893. #pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ] )
  2894. Arguments:
  2895. Line -- ptr to the source line (points at the '#' character)
  2896. Return Value:
  2897. None.
  2898. --*/
  2899. {
  2900. char *p;
  2901. // skip over '#' character
  2902. Line++;
  2903. // skip over any spaces between '#' and the next token
  2904. while (*Line == ' ' || *Line == '\t') {
  2905. Line++;
  2906. }
  2907. // find the first token
  2908. for (p = Line; isalpha(*p); ++p)
  2909. ;
  2910. *p = '\0';
  2911. if (strcmp(Line, "pragma") == 0) {
  2912. //
  2913. // found: #pragma
  2914. //
  2915. char c;
  2916. p++;
  2917. while (*p == ' ' || *p == '\t') {
  2918. p++;
  2919. }
  2920. //
  2921. // Set 'Line' to the start of the word following '#pragma' and
  2922. // move 'p' to the character following that word.
  2923. //
  2924. for (Line = p; isalpha(*p); ++p)
  2925. ;
  2926. //
  2927. // Null-terminate the keyword, but save the overwritten character
  2928. // for later.
  2929. //
  2930. c = *p;
  2931. *p = '\0';
  2932. if (strcmp(Line, "pack") != 0) {
  2933. //
  2934. // Might be "warning", "function" or "once". Ignore these.
  2935. //
  2936. return;
  2937. }
  2938. //
  2939. // Remove the null-terminator from the pragma and move 'p' to the
  2940. // first character after "#pragma pack"
  2941. //
  2942. *p = c;
  2943. while (*p == ' ' || *p == '\t') {
  2944. p++;
  2945. }
  2946. if (*p == '\0') {
  2947. //
  2948. // Found: "#pragma pack" all by itself. Reset packing to the
  2949. // default value.
  2950. //
  2951. PackModify(DEFAULTPACKINGSIZE);
  2952. return;
  2953. } else if (*p != '(') {
  2954. ExitErrMsg(FALSE, "Unknown '#pragma pack' syntax '%s'.\n", Line);
  2955. }
  2956. //
  2957. // skip over the '(' character and any whitespace
  2958. //
  2959. do {
  2960. p++;
  2961. } while (*p == ' ' || *p == '\t');
  2962. if (isdigit(*p)) {
  2963. //
  2964. // Found: '#pragma pack(NUMBER)'
  2965. //
  2966. PackModify(atol(p));
  2967. //
  2968. // Don't worry about the closing ')' - assume things are alright.
  2969. //
  2970. return;
  2971. } else if (*p == ')') {
  2972. //
  2973. // Found: '#pragma pack()'
  2974. //
  2975. PackModify(DEFAULTPACKINGSIZE);
  2976. return;
  2977. } else if (!isalpha(*p)) {
  2978. ExitErrMsg(FALSE, "Bad '#pragma pack' syntax '%s'.\n", Line);
  2979. return;
  2980. }
  2981. //
  2982. // Grab the next keyword following '#pragma pack('
  2983. //
  2984. for (Line = p; isalpha(*p); ++p)
  2985. ;
  2986. c = *p;
  2987. *p = '\0';
  2988. if (strcmp(Line, "push") == 0) {
  2989. //
  2990. // Restore the old character and skip over any whitespace
  2991. //
  2992. *p = c;
  2993. while (*p == ' ' || *p == '\t') {
  2994. p++;
  2995. }
  2996. if (*p == ',') {
  2997. //
  2998. // Skip the ',' and any whitespace
  2999. //
  3000. do {
  3001. p++;
  3002. } while (*p == ' ' || *p == '\t');
  3003. if (isdigit(*p)) {
  3004. //
  3005. // Found: "#pragma pack(push, n)"
  3006. //
  3007. PackPush(NULL);
  3008. PackModify(atoi(p));
  3009. } else if (isalpha(*p) || *p == '_') {
  3010. //
  3011. // Found an identifier after "#pragma pack(push, ".
  3012. // Scan ahead to end of identifier.
  3013. //
  3014. Line = p;
  3015. do {
  3016. p++;
  3017. } while (isalnum(*p) || *p == '_');
  3018. //
  3019. // null-terminate the identifier, in 'Line'
  3020. //
  3021. c = *p;
  3022. *p = '\0';
  3023. //
  3024. // Skip past whitespace
  3025. //
  3026. while (c == ' ' || c == '\t') {
  3027. p++;
  3028. c = *p;
  3029. }
  3030. // 'c' is the first non-white char after identifier
  3031. if (c == ')') {
  3032. //
  3033. // Found: "#pragma pack(push, identifier)"
  3034. //
  3035. PackPush(Line);
  3036. } else if (c == ',') {
  3037. //
  3038. // Expect a number as the last thing on the line
  3039. //
  3040. PackPush(Line);
  3041. PackModify(atoi(p+1));
  3042. } else {
  3043. ExitErrMsg(FALSE, "Unknown #pragma pack syntax '%s' at %s(%d)\n", p, SourceFileName, StatementLineNumber );
  3044. }
  3045. } else {
  3046. ExitErrMsg(FALSE, "Unknown #pragma pack syntax '%s'\n", p);
  3047. }
  3048. } else if (*p == ')') {
  3049. //
  3050. // Found: "#pragma pack(push)"
  3051. //
  3052. PackPush(NULL);
  3053. } else {
  3054. ExitErrMsg(FALSE, "Bad '#pragma pack(push)' syntax '%s' at %s(%d).\n", Line, SourceFileName, StatementLineNumber);
  3055. }
  3056. } else if (strcmp(Line, "pop") == 0) {
  3057. //
  3058. // Restore the old character and skip over any whitespace
  3059. //
  3060. *p = c;
  3061. while (*p == ' ' || *p == '\t') {
  3062. p++;
  3063. }
  3064. if (*p == ')') {
  3065. //
  3066. // Found: "#pragma pack(pop)"
  3067. //
  3068. PackModify(PackPop(NULL));
  3069. } else if (*p == ',') {
  3070. //
  3071. // Found: "#pragma pack(pop, identifier)"
  3072. //
  3073. p++;
  3074. while (*p == ' ' || *p == '\t') p++;
  3075. if (!(isalpha(*p) || *p == '_'))
  3076. ExitErrMsg(FALSE, "Bad '#pragma pack(pop)' syntax '%s' at %s(%d).\n", p, SourceFileName, StatementLineNumber);
  3077. Line = p;
  3078. do {
  3079. p++;
  3080. } while (isalnum(*p) || *p == '_');
  3081. *p = '\0';
  3082. PackModify(PackPop(Line));
  3083. } else {
  3084. ExitErrMsg(FALSE, "Bad '#pragma pack(pop)' syntax '%s' at %s(%d).\n", p, SourceFileName, StatementLineNumber);
  3085. }
  3086. } else {
  3087. ExitErrMsg(FALSE, "Bad '#pragma pack' syntax '%s' at %s(%d).\n", Line, SourceFileName, StatementLineNumber);
  3088. }
  3089. } else if (strcmp(Line, "line") == 0) {
  3090. //
  3091. // found: #line LINE_NUMBER "FILENAME"
  3092. //
  3093. int i;
  3094. //
  3095. // skip over any spaces between '#line' and the line number
  3096. //
  3097. p++;
  3098. while (*p == ' ' || *p == '\t') {
  3099. p++;
  3100. }
  3101. //
  3102. // copy in the new line number
  3103. //
  3104. SourceLineNumber = 0;
  3105. while (isdigit(*p)) {
  3106. SourceLineNumber = SourceLineNumber * 10 + *p - '0';
  3107. p++;
  3108. }
  3109. SourceLineNumber--;
  3110. //
  3111. // Skip over any spaces between line number and the filename
  3112. //
  3113. while (*p == ' ' || *p == '\t') {
  3114. p++;
  3115. }
  3116. //
  3117. // Skip over the opening quote
  3118. //
  3119. if (*p == '\"') {
  3120. p++;
  3121. } else {
  3122. ExitErrMsg(FALSE, "Badly-formed #line directive - filename missing");
  3123. }
  3124. //
  3125. // Copy in the filename, converting "\\" sequences to single '\'
  3126. //
  3127. for (i=0; *p && *p != '\"' && i<sizeof(SourceFileName)-1; ++i, ++p) {
  3128. if (*p == '\\' && p[1] == '\\') {
  3129. p++;
  3130. }
  3131. SourceFileName[i] = *p;
  3132. }
  3133. SourceFileName[i] = '\0';
  3134. StatementLineNumber = SourceLineNumber;
  3135. } else {
  3136. ExitErrMsg(FALSE, "Unknown '#' directive (%s).\n", Line);
  3137. }
  3138. }
  3139. BOOL
  3140. LexNextStatement(
  3141. void
  3142. )
  3143. /*++
  3144. Routine Description:
  3145. Read from the input file and perform lexical analysis. On return, an
  3146. entire C-language statement has been tokenized. Use CurrentToken(),
  3147. ConsumeToken(), and CurrentTokenIndex to access the tokenized statement.
  3148. The preprocessor recognizes #pragma and #line directives, ignoring all
  3149. other directives.
  3150. Arguments:
  3151. None.
  3152. Return Value:
  3153. TRUE if analysis successful.
  3154. - Tokens[] is filled in with the tokenized statement
  3155. - CurrentTokenIndex is set to 0
  3156. - StatmentLineNumber is the line number in the original header file
  3157. corresponding to the first token in the statement
  3158. - SourceFileName[] is the name of the current header file
  3159. - SourceFileLineNumber is the current line number in the header file
  3160. FALSE if end-of-file encountered.
  3161. --*/
  3162. {
  3163. static char Line[MAX_CHARS_IN_LINE+2]; // a line from the .pp file
  3164. static char *p; // ptr into Line[]
  3165. BOOL fParseDone;
  3166. //
  3167. // Clean up after the previous statment and prep for the next statement
  3168. //
  3169. ResetLexer();
  3170. StatementLineNumber = SourceLineNumber;
  3171. //
  3172. // Lex source lines until a complete statement is recognized. That
  3173. // occurs when a ';' character is found at file-scope.
  3174. //
  3175. do {
  3176. if (p == NULL || *p == '\0') {
  3177. do {
  3178. //
  3179. // Get an entire source line from the file, and set p to
  3180. // point to the first non-space character
  3181. //
  3182. if (feof(fpHeaders)) {
  3183. return FALSE;
  3184. }
  3185. SourceLineNumber++;
  3186. if (!fgets(Line, MAX_CHARS_IN_LINE, fpHeaders)) {
  3187. return FALSE;
  3188. }
  3189. for (p = Line; isspace(*p); ++p)
  3190. ;
  3191. } while (*p == '\0');
  3192. }
  3193. StatementLineNumber = SourceLineNumber;
  3194. p = LexOneLine(p, TRUE, &fParseDone);
  3195. } while (!fParseDone);
  3196. CurrentTokenIndex = 0;
  3197. return TRUE;
  3198. }
  3199. BOOL
  3200. ConsumeDeclSpecOpt(
  3201. BOOL IsFunc,
  3202. BOOL bInitReturns,
  3203. BOOL *pIsDllImport,
  3204. BOOL *pIsGuidDefined,
  3205. GUID *pGuid
  3206. )
  3207. /*++
  3208. Routine Description:
  3209. Comsumes a __declspec modifier. Returns are unaffected if the corresponding
  3210. __declspec is not found.
  3211. Accepts:
  3212. <not a __declspec keyword>
  3213. __declspec()
  3214. __declspec(naked) (only if parsing functions)
  3215. __declspec(thread) (only if parsing data)
  3216. __declspec(novtable) (only if parsing data)
  3217. __declspec(uuid(GUID)) (only if parsing data)
  3218. __declspec(dllimport) (both functions and data)
  3219. __declspec(dllexport) (both functions and data)
  3220. __declspec(align(x)) (only if parsing data)
  3221. Arguments:
  3222. IsFunc -- TRUE if parsing a function declaration, FALSE if parsing
  3223. a data/object declaration. Affects which keywords are
  3224. allowed within the __declspec.
  3225. bInitReturns -- TRUE if returns should be initialized to FALSE.
  3226. pIsDllImport -- [OPTIONAL OUT] set to TRUE if __declspec(dllimport) found
  3227. pIsGuidDefined -- [OPTIONAL OUT] set to TRUE if __declspec(uuid(GUID)) found
  3228. pGuid -- [OPTIONAL OUT] set to guid of __declspec(uuid(GUID)) if found.
  3229. Return Value:
  3230. TRUE if __declspec consumed OK, FALSE if __declspec parse error.
  3231. --*/
  3232. {
  3233. int OldTokenIndex;
  3234. OldTokenIndex = CurrentTokenIndex;
  3235. if (bInitReturns) {
  3236. if (pIsDllImport != NULL) *pIsDllImport = FALSE;
  3237. if (pIsGuidDefined != NULL) *pIsGuidDefined = FALSE;
  3238. }
  3239. if (CurrentToken()->TokenType != TK_DECLSPEC) {
  3240. // Reject: no __declspec found
  3241. goto dofail;
  3242. }
  3243. ConsumeToken();
  3244. if (CurrentToken()->TokenType != TK_LPAREN) {
  3245. // Reject: __declspec found without '(' following
  3246. goto dofail;
  3247. }
  3248. ConsumeToken();
  3249. if (CurrentToken()->TokenType == TK_RPAREN) {
  3250. // Accept: "__declspec ()"
  3251. ConsumeToken();
  3252. return TRUE;
  3253. }
  3254. else if (CurrentToken()->TokenType != TK_IDENTIFIER) {
  3255. goto dofail;
  3256. }
  3257. //handle cases for both data and functions
  3258. if (strcmp(CurrentToken()->Name, "dllimport") == 0) {
  3259. //Parsing: __declspec(dllimport
  3260. if (NULL != pIsDllImport) *pIsDllImport = TRUE;
  3261. ConsumeToken();
  3262. }
  3263. else if (strcmp(CurrentToken()->Name, "dllexport") == 0) {
  3264. //Parsing: __declspec(dllexport
  3265. ConsumeToken();
  3266. }
  3267. else if (IsFunc) {
  3268. if (strcmp(CurrentToken()->Name, "naked") == 0) {
  3269. //Parsing: __declspec(naked
  3270. ConsumeToken();
  3271. } else if (strcmp(CurrentToken()->Name, "noreturn") == 0) {
  3272. //Parsing: __declspec(noreturn
  3273. ConsumeToken();
  3274. } else if (strcmp(CurrentToken()->Name, "address_safe") == 0) {
  3275. //Parsing: __declspec(address_safe
  3276. ConsumeToken();
  3277. } else if (strcmp(CurrentToken()->Name, "noalias") == 0) {
  3278. //Parsing: __declspec(address_safe
  3279. ConsumeToken();
  3280. } else if (strcmp(CurrentToken()->Name, "restrict") == 0) {
  3281. //Parsing: __declspec(address_safe
  3282. ConsumeToken();
  3283. }
  3284. else goto dofail; //reject
  3285. }
  3286. else { //data
  3287. if (strcmp(CurrentToken()->Name, "thread") == 0) {
  3288. //Parsing: __declspec(thread
  3289. ConsumeToken();
  3290. }
  3291. else if (strcmp(CurrentToken()->Name, "novtable") == 0) {
  3292. //Parsing: __declspec(novtable
  3293. ConsumeToken();
  3294. }
  3295. else if (strcmp(CurrentToken()->Name, "uuid") == 0) {
  3296. GUID gTemp;
  3297. //Parsing: __declspec(uuid
  3298. ConsumeToken();
  3299. if (CurrentToken()->TokenType != TK_LPAREN) goto dofail;
  3300. //Parsing: __declspec(uuid(
  3301. ConsumeToken();
  3302. if (CurrentToken()->TokenType != TK_STRING) goto dofail;
  3303. //Parsing: __declspec(uuid(guid
  3304. if(!ConvertStringToGuid(CurrentToken()->Name, &gTemp)) goto dofail;
  3305. ConsumeToken();
  3306. if (CurrentToken()->TokenType != TK_RPAREN) goto dofail;
  3307. //Parsing: __declspec(uuid(guid)
  3308. ConsumeToken();
  3309. if (pIsGuidDefined != NULL) *pIsGuidDefined = TRUE;
  3310. if (pGuid != NULL) *pGuid = gTemp;
  3311. }
  3312. else if (strcmp(CurrentToken()->Name, "align") == 0) {
  3313. ConsumeToken();
  3314. if (CurrentToken()->TokenType != TK_LPAREN) goto dofail;
  3315. ConsumeToken();
  3316. expr();
  3317. if (CurrentToken()->TokenType != TK_RPAREN) goto dofail;
  3318. ConsumeToken();
  3319. }
  3320. else goto dofail; //reject
  3321. }
  3322. if (CurrentToken()->TokenType != TK_RPAREN) {
  3323. // Reject: expect ')' after __declspec(extended-decl-modifier)
  3324. goto dofail;
  3325. }
  3326. ConsumeToken();
  3327. // Accept: __declspec(extended-decl-modifier)
  3328. return TRUE;
  3329. dofail:
  3330. CurrentTokenIndex = OldTokenIndex;
  3331. return FALSE;
  3332. }
  3333. PTYPEINFOELEMENT
  3334. TypeInfoElementAllocateLink(
  3335. PTYPEINFOELEMENT *ppHead,
  3336. PTYPEINFOELEMENT pThis,
  3337. TYPESINFO *pType
  3338. )
  3339. {
  3340. /*++
  3341. Routine Description:
  3342. Allocates a TYPEINFOELEMENT and linked it to the end of the list.
  3343. Arguments:
  3344. ppHead - [IN/OUT] ptr ptr to the head of the list.
  3345. pThis - [IN] ptr to the tail of the list.
  3346. pType - [IN] ptr to the typeinfo to add to the list.
  3347. Return Value:
  3348. NON-NULL - New tail.
  3349. NULL - Failure.
  3350. --*/
  3351. PTYPEINFOELEMENT pNew= GenHeapAlloc(sizeof(struct TypeInfoListElement));
  3352. if (NULL == pNew) ExitErrMsg(FALSE, "Out of memory!");
  3353. pNew->pNext = NULL;
  3354. pNew->pTypeInfo = pType;
  3355. if (NULL == pThis) *ppHead = pNew;
  3356. else pThis->pNext = pNew;
  3357. return pNew;
  3358. }
  3359. BOOL
  3360. AddVariable(
  3361. char *Name,
  3362. GUID * pGuid
  3363. )
  3364. {
  3365. /*++
  3366. Routine Description:
  3367. Adds a variable to the list of declared global variabled.
  3368. Arguments:
  3369. Name - [IN] ptr to name of variable to add.
  3370. pGuid - [OPTIONAL IN] ptr to guid for this variable.
  3371. Return Value:
  3372. TRUE - if success.
  3373. --*/
  3374. PKNOWNTYPES pKnownTypes;
  3375. int Len;
  3376. if(NULL == Name) return FALSE;
  3377. //Already in the tree
  3378. pKnownTypes = RBFind(VarsList, Name);
  3379. if (NULL != pKnownTypes) {
  3380. //replace guid in list if pGuid != NULL and ignore the duplication
  3381. if (NULL != pGuid) {
  3382. pKnownTypes->Flags |= BTI_HASGUID;
  3383. pKnownTypes->gGuid = *pGuid;
  3384. }
  3385. return TRUE;
  3386. }
  3387. //Create a KNOWNTYPES structure for variable
  3388. Len = sizeof(KNOWNTYPES) + strlen(Name) + 1;
  3389. pKnownTypes = GenHeapAlloc(Len);
  3390. if(NULL == pKnownTypes) return FALSE;
  3391. memset(pKnownTypes, 0, Len);
  3392. pKnownTypes->TypeName = pKnownTypes->Names;
  3393. strcpy(pKnownTypes->Names, Name);
  3394. if(NULL != pGuid) {
  3395. pKnownTypes->Flags |= BTI_HASGUID;
  3396. pKnownTypes->gGuid = *pGuid;
  3397. }
  3398. RBInsert(VarsList, pKnownTypes);
  3399. return TRUE;
  3400. }
  3401. VOID
  3402. UpdateGuids(
  3403. VOID
  3404. )
  3405. {
  3406. /*++
  3407. Routine Description:
  3408. Looks for variables of whose name starts with IID_ and assigned a guid structure.
  3409. The IID_ is striped and the guid of the corresponding struct is updated
  3410. Arguments:
  3411. None.
  3412. Return Value:
  3413. None.
  3414. --*/
  3415. PKNOWNTYPES pThis;
  3416. PKNOWNTYPES pLookup;
  3417. char *LookupName;
  3418. for(pThis = VarsList->pLastNodeInserted; pThis != NULL; pThis = pThis->Next) {
  3419. //test if name has guid associated with it and that it begins with IID_
  3420. if ((pThis->Flags & BTI_HASGUID) &&
  3421. pThis->TypeName[0] == 'I' &&
  3422. pThis->TypeName[1] == 'I' &&
  3423. pThis->TypeName[2] == 'D' &&
  3424. pThis->TypeName[3] == '_' )
  3425. {
  3426. //Attempt to find a structure with the name except the IID_
  3427. LookupName = pThis->TypeName + 4; //skip the IID_
  3428. pLookup = RBFind(StructsList, LookupName);
  3429. if(NULL != pLookup) {
  3430. //if types does not have a GUID defined already, copy guid from here
  3431. if (!(pLookup->Flags & BTI_HASGUID)) {
  3432. pLookup->Flags |= BTI_HASGUID;
  3433. pLookup->gGuid = pThis->gGuid;
  3434. }
  3435. }
  3436. }
  3437. }
  3438. }