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.

9131 lines
263 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. genthnk.c
  5. Abstract:
  6. This program generates thunks.
  7. Author:
  8. 08-Jul-1995 JonLe
  9. Revision History:
  10. July 2001 JayKrell
  11. integrated from base\wow64\tools to base\tools
  12. merged in checked changes from base\mvdm\MeoWThunks\tools\genthnk
  13. -G to ignore functions with no prototype
  14. skip leading @ on exports
  15. let @Else work with @IfApiCode
  16. add -LessTrailingWhitespace option to aid formating
  17. let @Else work with a few @IfFoo forms
  18. August 2001 JayKrell
  19. fixed IfApiRet broken above
  20. January 2002 JayKrell
  21. integrated /private/winfuse_longhorn/base/tools to /lab01_n/base/win32/fusion/tools
  22. some -W4 cleanup
  23. --*/
  24. #pragma warning(disable:4057) /* char vs. unsigned char mixup */
  25. #pragma warning(disable:4100) /* unreferenced formal parameter */
  26. #pragma warning(disable:4115) /* named type definition in parentheses */
  27. #pragma warning(disable:4127) /* conditional expression is constant */
  28. #pragma warning(disable:4201) /* nameless struct/union */
  29. #pragma warning(disable:4214) /* bit field types other than int */
  30. #pragma warning(disable:4267) /* conversion from 'size_t' to 'int', possible loss of data */
  31. #pragma warning(disable:4706) /* assignment within conditional expression */
  32. #include "nt.h"
  33. #include "ntrtl.h"
  34. #include "nturtl.h"
  35. #include "windows.h"
  36. #include "imagehlp.h"
  37. #include <ctype.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include "gen.h"
  42. // bitfield values to indicate which platform an API should be switched in on.
  43. #define API_NONE 0
  44. #define API_WIN95 1
  45. #define API_WIN98 2
  46. #define API_NT4 4
  47. #define API_NT5 8
  48. #define API_WIN9x (API_WIN95 | API_WIN98)
  49. #define API_NTx (API_NT4 | API_NT5)
  50. #define API_ALL (API_WIN9x | API_NTx)
  51. #define API_SHIFT_WIN9x 0 // shift API bits right 0 to make Win9x leftmost
  52. #define API_SHIFT_NTx 2 // shift API bits right 2 to make NTx leftmost
  53. // This is the new VC6 import structure. VC6 import lib spec is checked
  54. // in as wx86\doc\vc6.doc. Contact Dan Spalding or Kathleen Herold for
  55. // more info. Or look at sdktools\vctools\coff\deflib.h ImportHdr.
  56. typedef struct ImgImportHdr {
  57. WORD Sig1; // always 0 (IMAGE_FILE_MACHINE_UNKNOWN)
  58. WORD Sig2; // always ffff (IMPORT_HDR_SIG2)
  59. WORD Version;
  60. WORD Machine;
  61. DWORD TimeStamp;
  62. DWORD SizeOfData; // count of bytes in strings that follow
  63. union {
  64. WORD Ordinal;
  65. WORD Hint;
  66. };
  67. WORD Type : 2; // IMPORT_TYPE
  68. WORD NameType : 3; // IMPORT_NAME_TYPE
  69. WORD Reserved : 11;// Reserved. Must be 0.
  70. } VC6_IMAGE_IMPORT_HEADER, *PVC6_IMAGE_IMPORT_HEADER;
  71. enum IMPORT_TYPE
  72. {
  73. IMPORT_CODE = 0,
  74. IMPORT_DATA = 1,
  75. IMPORT_CONST = 2,
  76. };
  77. enum IMPORT_NAME_TYPE
  78. {
  79. IMPORT_ORDINAL,
  80. IMPORT_NAME,
  81. IMPORT_NAME_NO_PREFIX,
  82. IMPORT_NAME_UNDECORATE
  83. };
  84. // end of VC6 import structure
  85. // string to put in front of all error messages so that BUILD can find them.
  86. const char *ErrMsgPrefix = "NMAKE : U8600: 'GENTHNK' ";
  87. // template sections types
  88. char szIFUNC[]= "IFunc";
  89. char szEFUNC[]= "EFunc";
  90. char szEFAST[]= "EFast";
  91. char szTYPES[]= "Types";
  92. char szCODE[] = "Code";
  93. char szFAILTYPES[] = "FailTypes";
  94. char szMACROS[]="Macros";
  95. // template properties
  96. char szTEMPLENAME[]= "TemplateName";
  97. char szMACRONAME[] = "MacroName";
  98. char szTYPENAME[] = "TypeName";
  99. char szINDLEVEL[] = "IndLevel";
  100. char szDIRECTION[] = "Direction";
  101. char szNUMARGS[] = "NumArgs";
  102. char szCGENBEG[] = "Begin"; // default codeburst name
  103. char szCGENEND[] = "End";
  104. char szUSE[] = "Use";
  105. char szALSO[] = "Also";
  106. char szNOTYPE[] = "NoType";
  107. char szCASE[] = "Case";
  108. // substitution macros
  109. const
  110. char szTEMPLATE[]="Template";
  111. const
  112. char szDLLNAME[]="DllName";
  113. const
  114. char szXPTNAME[]="XPTName";
  115. const
  116. char szDLLTARGET[]="DllTarget";
  117. const
  118. char szAPIFNRET[]="ApiFnRet";
  119. const
  120. char szAPIFNMOD[]="ApiFnMod";
  121. const
  122. char szAPINAME[]="ApiName";
  123. const
  124. char szAPINAMESKIP[]="ApiNameSkip";
  125. const
  126. char szAPIFORWARD[]="ApiForward";
  127. const
  128. char szAPINUM[]="ApiNum";
  129. const
  130. char szAPIUNKNOWN[]="ApiUnknown";
  131. const
  132. char szAPINODECL[]="ApiNoDecl";
  133. const char szISAPIDECLARED[]="IsApiDeclared"; /* like previous, but a boolean expression */
  134. const
  135. char szFASTCALL[]="FastCall";
  136. const
  137. char szSLOWCALL[]="SlowCall";
  138. const
  139. char szFASTX2NMETH[]="FastX2NMethod";
  140. const
  141. char szSLOWX2NMETH[]="SlowX2NMethod";
  142. const
  143. char szFATX2NMETH[]="FatX2NMethod";
  144. const
  145. char szMETHODNUMBER[]="MethodNumber";
  146. const
  147. char szRETSIZE[]="RetSize";
  148. const
  149. char szUNALIGNEDTAG64[]="UnalignedTag64";
  150. const
  151. char szARGSIZE[]="ArgSize";
  152. const
  153. char szARGTYPE[]="ArgType";
  154. const
  155. char szARGHOSTTYPE[] = "ArgHostType";
  156. const
  157. char szARGTYPEIND[]="ArgTypeInd";
  158. const
  159. char szARGHOSTTYPEIND[]="ArgHostTypeInd";
  160. const
  161. char szARGNAME[]="ArgName";
  162. const
  163. char szARGNAMEHOSTCASTED[]="ArgHostName";
  164. const
  165. char szARGVAL[]="ArgVal";
  166. const
  167. char szFUNCARGNUM[]="FuncArgNum";
  168. const
  169. char szARGMOD[]="ArgMod";
  170. const
  171. char szARGPOSTMOD[]="ArgPostMod";
  172. const
  173. char szARGLIST[]="ArgList";
  174. const
  175. char szIFAPIRET[]="IfApiRet";
  176. const char szDOESAPIRETURNVOID[] = "DoesApiReturnVoid"; /* like previous, but a boolean expression */
  177. const
  178. char szIFARGS[]="IfArgs";
  179. const
  180. char szARGMORE[]="ArgMore";
  181. const
  182. char szAPILIST[]="ApiList";
  183. const
  184. char szAPIMORE[]="ApiMore";
  185. const
  186. char szLISTCOL[]="ListCol";
  187. const
  188. char szARGLOCAL[]="ArgLocal";
  189. const
  190. char szARGOFF[]="ArgOff";
  191. const
  192. char szARGADDR[]="ArgAddr";
  193. const
  194. char szEXPORTLIST[]="ExportList";
  195. const
  196. char szEXPNAME[]= "ExpName";
  197. const
  198. char szIFEXPFORWARD[]= "IfExpForward";
  199. const
  200. char szADDRARGSLIST[]="AddrArgsList";
  201. const
  202. char szNARGTYPE[]="NArgType";
  203. const
  204. char szNARGNAME[]="NArgName";
  205. const
  206. char szIFRETTYPE[]="IfRetType";
  207. const
  208. char szIFORDINALS[]="IfOrdinals";
  209. const
  210. char szAPISTRINGS[]="ApiStrings";
  211. const
  212. char szDBGSINDEX[]="DbgsIndex";
  213. const
  214. char szDBGSLIST[]="DbgsList";
  215. const
  216. char szDBGSSTRINGS[]="DbgsStrings";
  217. const
  218. char szDBGSMORE[]="DbgsMore";
  219. const
  220. char szCPPEXPORT[]="CppExport";
  221. const
  222. char szCEXPORT[]="CExport";
  223. const
  224. char szCPPOUTPUT[]="CppOutput";
  225. const
  226. char szCOUTPUT[]="COutput";
  227. const
  228. char szAPIDECLSPEC[]="ApiDeclSpec";
  229. const
  230. char szIFAPICODE[]="IfApiCode";
  231. const
  232. char szRETTYPE[]="RetType";
  233. const
  234. char szMARG[]="MArg";
  235. const
  236. char szMEMBERTYPES[]="MemberTypes";
  237. const
  238. char szBTOTMEMBERTYPES[]="BtoTMemberTypes";
  239. const
  240. char szFORCETYPE[]="ForceType";
  241. const
  242. char szLOG[]="Log";
  243. const
  244. char szRTOLTYPES[]= "RtoLTypes";
  245. const
  246. char szIFNOTRETTYPE[]="IfNotRetType";
  247. const
  248. char szIFISMEMBER[]="IfIsMember";
  249. const
  250. char szIFNISMEMBER[]="IfNotIsMember";
  251. const
  252. char szIFISBITFIELD[]="IfIsBitfield";
  253. const
  254. char szIFNISBITFIELD[]="IfNotIsBitfield";
  255. const
  256. char szIFISARRAY[]="IfIsArray";
  257. const
  258. char szIFNISARRAY[]="IfNotIsArray";
  259. const
  260. char szARGARRAYELEMENTS[]="ArrayElements";
  261. const
  262. char szIFPOINTERTOPTRDEP[]="IfPointerToPtrDep";
  263. const
  264. char szIFNPOINTERTOPTRDEP[]="IfNotPointerToPtrDep";
  265. const
  266. char szISPOINTERTOPTRDEP[]="IsPointerToPtrDep";
  267. const
  268. char szIFPTRDEP[]="IfPtrDep";
  269. const
  270. char szIFNPTRDEP[]="IfNotPtrDep";
  271. const
  272. char szIFINT64DEPUNION[]="IfInt64DepUnion";
  273. const
  274. char szIFNINT64DEPUNION[]="IfNotInt64DepUnion";
  275. const
  276. char szNL[]="NL";
  277. const
  278. char szINDENT[]="Indent";
  279. const
  280. char szNOFORMAT[]="NoFormat";
  281. const
  282. char szALIGN[]="Align";
  283. char szCOMMENT[]="Comment";
  284. const
  285. char szOFFSET[]="OffSet";
  286. const
  287. char szHOSTAPPEND[]="Host";
  288. char szCARG[]="CArg";
  289. char szCARGEXIST[]="CArgExist";
  290. const
  291. char szFORCASE[]="ForCase";
  292. const
  293. char szCNUMBER[]="CNumber";
  294. const
  295. char szISINTFORWARD[]="IsIntForward";
  296. const
  297. char szISNOTINTFORWARD[]="IsNotIntForward";
  298. // if support
  299. const
  300. char szIF[]="If";
  301. const
  302. char szELSE[]="Else";
  303. const
  304. char szOR[]="Or";
  305. const
  306. char szAND[]="And";
  307. const
  308. char szNOT[]="Not";
  309. const
  310. char szARGUNIONULARGEINTEGER[]="PULARGE_INTEGER";
  311. const
  312. char szARGUNIONLARGEINTEGER[]="PLARGE_INTEGER";
  313. BOOL g_fLessTrailingWhitespace;
  314. extern char sz__PTR64[];
  315. #define MAX_ALSO 80
  316. #define MAX_CODEBURST 20
  317. #define MAX_NOTYPE 32
  318. typedef struct tagCODEBURST {
  319. char *Name;
  320. } CODEBURST;
  321. CODEBURST CodeBursts[MAX_CODEBURST];
  322. typedef struct _Templates{
  323. LIST_ENTRY TempleEntry;
  324. char *Name;
  325. int IndLevel;
  326. TOKENTYPE tkDirection;
  327. PKNOWNTYPES pktType;
  328. char *Comment;
  329. char *CodeBurst[MAX_CODEBURST];
  330. char *NoTypes[MAX_NOTYPE];
  331. PLIST_ENTRY pCaseList;
  332. char Buffer[1];
  333. }TEMPLES, *PTEMPLES;
  334. typedef struct _CGenerate {
  335. LIST_ENTRY CGenerateEntry;
  336. FILE *fp;
  337. FILE *fpC;
  338. char *FileNameC;
  339. char *FileBaseNameC;
  340. FILE *fpCpp;
  341. char *FileNameCpp;
  342. char *FileBaseNameCpp;
  343. char TempleName[1];
  344. }CGENERATE, *PCGENERATE;
  345. FILE *fpLog; // file pointer to optional log file for @Log() calls
  346. //
  347. // handy macro to knock out the hi bit in implib style ordinals
  348. //
  349. #define IMPORDINAL(o) ((o) & ~0x80000000)
  350. //
  351. // Structure definining the list of arguments for a function
  352. //
  353. typedef struct _ArgumentsList {
  354. LIST_ENTRY ArgumentsEntry; // ptr to prev and next arg
  355. PKNOWNTYPES pKnownTypes; // type of this arg
  356. PKNOWNTYPES pStructType; // cache used by MemberTypes()
  357. DWORD ArgSize; // size of this arg
  358. BOOL IsPtr64; // TRUE if this arg is __ptr64
  359. int OffSet; // offset from stack for this arg
  360. int IndLevel; // indirection level
  361. TOKENTYPE tkDirection; // TK_NONE, TK_IN, TK_OUT, TK_INOUT
  362. TOKENTYPE Mod; // modifier (TK_CONST/VOLATILE/NONE)
  363. TOKENTYPE SUEOpt; // TK_STRUCT/ENUM/UNION/NONE
  364. char *Type; // typename for this arg
  365. TOKENTYPE PostMod; // modifier (TK_CONST/VOLATILE/NONE)
  366. TOKENTYPE PrePostMod; // modifier (TK_CONST/VOLATILE/NONE)
  367. char *Name; // argument name (may be a nonameX)
  368. char *ArgLocal; // name of local var containing copy of arg
  369. char *HostCastedName; // Contains full name of struct member with
  370. // host casts or NULL
  371. BOOL fRequiresThunk; // TRUE if arg type contains a nested
  372. // function pointer (and hence needs
  373. // special thunking)
  374. BOOL fNoType; // TRUE if types templates should *not*
  375. // be expanded for this param.
  376. BOOL fIsMember; // This arg is actually a member of an array
  377. BOOL bIsBitfield; // Determines if this is a bitfield
  378. int BitsRequired; // Number of bits required for bitfield
  379. BOOL bIsArray; // This member is an array
  380. int ArrayElements; // Number of elements in the array
  381. } ARGSLIST, *PARGSLIST;
  382. //
  383. // Structure containing the list of macro arguments
  384. //
  385. typedef struct _MacroArgsList {
  386. int NumArgs;
  387. LPSTR ArgText[1];
  388. } MACROARGSLIST, *PMACROARGSLIST;
  389. typedef struct _MLListEntry {
  390. LIST_ENTRY ListEntry;
  391. PMACROARGSLIST pMArgs;
  392. } MLLISTENTRY, *PMLLISTENTRY;
  393. #define MAX_MACRO_STACK 20
  394. PMACROARGSLIST MacroStack[MAX_MACRO_STACK];
  395. int MacroStackTop;
  396. //
  397. // This defines the first method number that would not be supported as a
  398. // fast or slow method call. If this is to be changed then FastN2X and SlowN2X
  399. // worker routines need to be addeed in whole32.dll
  400. #define MAXFASTN2XMETHODNUMBER 16
  401. //
  402. // This defines the maximum number of parameters that are allowed to be in a
  403. // FastX2N or SlowX2N method call. To change it new code would have to be
  404. // added to FastX2N and SlowX2N in whole32\methods.c to deal with the
  405. // additional number of parameters.
  406. #define MAXX2NPARAMETERS 10
  407. typedef enum {
  408. UNKNOWNMETHOD = 0,
  409. FATX2NMETHOD = 1,
  410. FASTX2NMETHOD = 2,
  411. SLOWX2NMETHOD = 3
  412. } METHODTYPE;
  413. typedef struct _ExportDebugInfo {
  414. LIST_ENTRY ExportsDbgEntry;
  415. LIST_ENTRY ArgsListHead;
  416. struct _ExportDebugInfo *IntForward;
  417. int ArgsSize;
  418. ULONG Function;
  419. char *ExtForward;
  420. char *ExportName;
  421. char *CplusDecoration;
  422. ULONG Ordinal;
  423. // 0 = known fn, -1 incomplete declaration, 1 no declaration
  424. char UnKnownApi;
  425. BOOLEAN Data;
  426. BOOLEAN PrivateNamed;
  427. CHAR FastCall;
  428. BYTE ApiPlatform; // the API_ bit collection
  429. METHODTYPE X2NMethodType;
  430. ULONG MethodNumber;
  431. char Buffer[1];
  432. }EXPORTSDEBUG, *PEXPORTSDEBUG;
  433. typedef struct _DebugStringsList {
  434. LIST_ENTRY DebugStringsEntry;
  435. char *Name;
  436. char *ArgFormat;
  437. char *RetFormat;
  438. char Buffer[1];
  439. } DEBUGSTRINGS, *PDEBUGSTRINGS;
  440. typedef struct _CGenerateState {
  441. PEXPORTSDEBUG ExportsDbg;
  442. PDEBUGSTRINGS DebugStrings;
  443. PCGENERATE CGen;
  444. PTEMPLES Temple; // template for this func (may be IFunc or EFunc)
  445. PKNOWNTYPES ApiTypes;
  446. int ApiNum;
  447. PARGSLIST pArgsList;
  448. int ListCol;
  449. BOOLEAN MoreApis;
  450. BOOLEAN ExTemplate; // true if Temp is an EFunc template with a 'Begin='
  451. PTEMPLES TempleEx; // EFunc for this API (if there is one)
  452. int CodeBurstIndex;
  453. PTEMPLES CurrentTemple; // This is the template that is currently being expanded.
  454. PMACROARGSLIST pMacroArgsList;
  455. PCHAR *MemberNoType; // Additional set of notypes to applyPMACROARGSLIST pMacroArgsList;
  456. int CaseNumber; // Number of the current Case being expanded.
  457. PLIST_ENTRY pCaseList;
  458. PMACROARGSLIST pCaseArgsList;
  459. } CGENSTATE, *PCGENSTATE;
  460. int BeginCBI; // CodeBurstIndex for 'Begin='
  461. PKNOWNTYPES NIL; // for red-black trees
  462. PRBTREE FuncsList;
  463. PRBTREE TypeDefsList;
  464. PRBTREE StructsList;
  465. RBTREE FakeFuncsList;
  466. LIST_ENTRY TypeTempleList;
  467. LIST_ENTRY FailTempleList;
  468. LIST_ENTRY IFuncTempleList;
  469. LIST_ENTRY EFuncTempleList;
  470. LIST_ENTRY EFastTempleList;
  471. LIST_ENTRY CodeTempleList;
  472. LIST_ENTRY CGenerateList;
  473. LIST_ENTRY ExportsList;
  474. LIST_ENTRY DebugStringsList;
  475. LIST_ENTRY MacroList;
  476. ULONG NumDebugStringsEntries;
  477. BOOL MapViewDll(char *DllName);
  478. char DllName[MAX_PATH+1]= "";
  479. char ExplicitDllBaseName[MAX_PATH+1] = "UNSPECIFIED";
  480. char *DllBaseName = ExplicitDllBaseName;
  481. PVOID DllMappedBase = NULL;
  482. ULONG_PTR DllRvaOffset;
  483. PULONG DllFunctions = NULL;
  484. PUSHORT DllNameOrdinals = NULL;
  485. PULONG DllNameTable = NULL;
  486. ULONG DllExportDirSize;
  487. PIMAGE_EXPORT_DIRECTORY DllExportDir;
  488. BOOL MapViewImplib(char *ImplibName);
  489. char ImplibName[MAX_PATH+1]="";
  490. char *ImplibBaseName = NULL;
  491. PVOID ImplibMappedBase= NULL;
  492. ULONG ImplibNumSymbols=0;
  493. PULONG ImplibSymbolMembers=NULL;
  494. PCHAR ImplibSymbolNames=NULL;
  495. char szIMPPREFIX[]="__imp_";
  496. char szIDATA5[]=".idata$5";
  497. char szTEXT[]=".text";
  498. char szINTFORWARD[]="_IntForward_";
  499. char XptName[MAX_PATH+1]= "";
  500. char *XptBaseName = NULL;
  501. // these are used to report errors while parsing .tpl files
  502. char *TemplateFileName;
  503. int TemplateLine;
  504. char iHandleCpp = 0; // if == 0, Don't use CPP macros, and warn if CPP exports found
  505. // if < 0, Don't use CPP macros, no warn if CPP exports found
  506. // if > 0, Use CPP macros.
  507. BOOL bIgnorePrototypeError;
  508. BOOL bNoFuzzyLogic;
  509. BOOL bUseExpListAndImplib;
  510. BOOL bWarnAboutNestedFuncPtrs;
  511. BOOL bUseDirection = TRUE;
  512. BOOL bStripNewline = TRUE;
  513. int OutputColumn = 0;
  514. int IndentLevel = 0;
  515. BOOL bFirstCharHit = FALSE;
  516. #define INDENTSIZE 4
  517. void SetInternalForwards(void);
  518. BOOL ExtractXpt(char *XptName, char *DllName);
  519. BOOL ExtractExports(void);
  520. BOOL ExtractPpm(char *FileName);
  521. BOOL ExtractTemples(char *FileName);
  522. BOOL ExtractCGenerate(char *pNames);
  523. BOOL ExtractImplib(char *LibName);
  524. char *CopyField(char *pDst, char *pSrc, int Len, char Sep);
  525. void DumpTemplate(PTEMPLES ptpl, FILE *fp);
  526. PTEMPLES GetTemplate(PLIST_ENTRY pHeadList, char *TempleName);
  527. char *CGenerate(char *pSrc, PCGENSTATE pCGenState);
  528. char *CGenerateEx(char *pSrc, PCGENSTATE pCGenState, char *OutBuffer, SIZE_T MaxLen, SIZE_T *BytesReturned);
  529. char *ListApis(char *pSrc, PCGENSTATE pCGenState, BOOL bExports);
  530. char *ListArgs(char *pSrc, PCGENSTATE pCGenState, BOOL Always);
  531. void ProcessTemple(PCGENSTATE pCGenState);
  532. char *IncludeTemplate(char *pSrc, PCGENSTATE pCGenState);
  533. char *IncludeTypes(char *pSrc, PCGENSTATE pCGenState, BOOL bRtoL);
  534. char *MemberTypes(char *pSrc, PCGENSTATE pCGenState, BOOL bBtoT);
  535. char *IfNotRetType(char *pSrc, PCGENSTATE pCGenState);
  536. char *IncludeRetType(char *pSrc, PCGENSTATE pCGenState);
  537. char *WriteMore(char *pSrc, PCGENSTATE pCGenState, BOOL bMore);
  538. BOOL AddToExportsList(PEXPORTSDEBUG pExportsDebug);
  539. PEXPORTSDEBUG FindInExportsList(char *Name);
  540. char *SkipSubExpression(char *pSrc, char **pSubExpression);
  541. PKNOWNTYPES BuildFakeTypesInfo(PEXPORTSDEBUG pExportsDbg, PKNOWNTYPES pKnownTypes);
  542. void WriteListColumn(PCGENSTATE pCGenState);
  543. char *GetAltExportName(char *Buffer, PCGENSTATE pCGenState, int Len);
  544. void BuildArgsList(PTEMPLES pTempleEx, PFUNCINFO funcinfo, PLIST_ENTRY pListHead);
  545. char *IfApiRet(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult);
  546. char *DoesApiReturnVoid(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult);
  547. char *IfApiCode(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult);
  548. char *IfRetType(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult);
  549. char *IfArgs(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult);
  550. void ApiStrings(PCGENSTATE pCGenState);
  551. int GetFuncArgNum(PCGENSTATE pCGenState);
  552. int GetFuncIndex(PCGENSTATE pCGenState, char *FuncTypeName);
  553. char *ListDbgs(char *pSrc, PCGENSTATE pCGenState);
  554. void WriteDbgsStrings(char *pSrc, PCGENSTATE pCGenState);
  555. int GetRetSize(PCGENSTATE pCGenState);
  556. int GetArgSize(PEXPORTSDEBUG ExportDebug);
  557. char *GetOffSet(char *pSrc, char *Buffer);
  558. char *LexMacroArgs(char *pch);
  559. PLIST_ENTRY ListFromTempleType(char *TempleType);
  560. void UseLogMacros(char *pLogName);
  561. char *UpdateLog(char *pSrc, PCGENSTATE pCGenState);
  562. BOOL IsPointerToPtrDep(PARGSLIST pArgsList);
  563. char* ForceTypeExpand( char *pSrc, PCGENSTATE pCGenState);
  564. VOID SetArgListToTypeForArg(PARGSLIST pArgsList, PARGSLIST pArgsListOld, char * pTypeName);
  565. void StripTrailingWhitespaceFromString(char * s);
  566. char * SkipLeadingWhitespace(char * s);
  567. BOOL IsWhitespaceCharacter(char c);
  568. BOOLEAN
  569. IsFastCall(
  570. PCGENSTATE pCGenState
  571. );
  572. METHODTYPE
  573. GetX2NMethodType(
  574. PCGENSTATE pCGenState
  575. );
  576. char *
  577. GetAddrFirstArg(
  578. PCGENSTATE pCGenState,
  579. char *Buffer,
  580. int BuffLen
  581. );
  582. PKNOWNTYPES
  583. IsSameType(
  584. PKNOWNTYPES pktArgs,
  585. int IndLevel,
  586. TOKENTYPE tkArgDirection,
  587. char *tplTypeName,
  588. int tplIndLevel,
  589. TOKENTYPE tkTypeDirection,
  590. BOOL bScanBaseTypes
  591. );
  592. char *
  593. WriteArgAddr(
  594. char *pSrc,
  595. PCGENSTATE pCGenState,
  596. char *Buffer,
  597. int BuffLen
  598. );
  599. BOOL
  600. WriteArgLocal(
  601. PCGENSTATE pCGenState,
  602. char *Buffer,
  603. int BuffLen
  604. );
  605. BOOL
  606. AddTemple(
  607. char *TempleType,
  608. char *TempleName,
  609. char *Comment,
  610. char *IndLevel,
  611. char *pCCode[MAX_CODEBURST],
  612. TOKENTYPE tkDirection,
  613. char *Also[MAX_ALSO],
  614. int AlsoCount,
  615. char *NoType[MAX_NOTYPE],
  616. int NoTypeCount,
  617. PLIST_ENTRY pCaseList
  618. );
  619. int
  620. GetCodeBurstIndex(
  621. char *BurstName
  622. );
  623. int
  624. GetExistingCodeBurstIndex(
  625. char *BurstName
  626. );
  627. BOOLEAN
  628. ExpandMacro(
  629. char *MacroName,
  630. PCGENSTATE pCGenState,
  631. char **ppIn,
  632. char *OutBuffer,
  633. SIZE_T MaxLen,
  634. SIZE_T *BytesReturned
  635. );
  636. BOOLEAN
  637. TempleHasNoCodeBursts(
  638. PTEMPLES pTemple
  639. );
  640. void
  641. PlatformSwitchStart(
  642. PCGENSTATE pCGenState,
  643. BYTE ApiPlatform
  644. );
  645. void
  646. PlatformSwitchEnd(
  647. PCGENSTATE pCGenState,
  648. BYTE ApiPlatform
  649. );
  650. void
  651. PlatformSwitchEndTable(
  652. PCGENSTATE pCGenState,
  653. BYTE ApiPlatform
  654. );
  655. char *
  656. ExtractBoolean1(
  657. char *pSrc,
  658. PCGENSTATE pCGenState,
  659. BOOLEAN *result
  660. );
  661. char *
  662. ExtractBoolean2(
  663. char *pSrc,
  664. PCGENSTATE pCGenState,
  665. BOOLEAN *result1,
  666. BOOLEAN *result2
  667. );
  668. void
  669. WriteBoolean (
  670. char *pSrc,
  671. BOOL Value
  672. );
  673. char *CPlatformSwitches[] = { "",
  674. "(%s==0x0400)",
  675. "(%s>0x0400)",
  676. "(%s>=0x0400)" };
  677. char *AsmPlatformSwitches[] = { "",
  678. "(%s_ASM EQ 0400h)",
  679. "(%s_ASM GT 0400h)",
  680. "(%s_ASM GE 0400h)" };
  681. BOOL
  682. ExpandTemple(PTEMPLES ptpl,
  683. int CodeBurstIndex,
  684. PCGENSTATE pCGenState)
  685. {
  686. PLIST_ENTRY pOldCaseList;
  687. PTEMPLES pOldCurrentTemple;
  688. char *pSrc = ptpl->CodeBurst[CodeBurstIndex];
  689. if (NULL == pSrc) {
  690. return FALSE;
  691. }
  692. pSrc = ptpl->CodeBurst[CodeBurstIndex];
  693. while (*pSrc && !isgraph(*pSrc)) {
  694. pSrc++;
  695. }
  696. if ('\0' == *pSrc) {
  697. return FALSE;
  698. }
  699. //
  700. // Expand the type here
  701. pOldCurrentTemple = pCGenState->CurrentTemple;
  702. pOldCaseList = pCGenState->pCaseList;
  703. if(ptpl->pCaseList != NULL &&
  704. !IsListEmpty(ptpl->pCaseList)) {
  705. pCGenState->pCaseList = ptpl->pCaseList;
  706. }
  707. pCGenState->CurrentTemple = ptpl;
  708. CGenerate(pSrc, pCGenState);
  709. pCGenState->CurrentTemple = pOldCurrentTemple;
  710. pCGenState->pCaseList = pOldCaseList;
  711. return TRUE;
  712. }
  713. PVOID CheckHeapAlloc(SIZE_T Size) {
  714. PVOID pMem;
  715. pMem = GenHeapAlloc(Size);
  716. if(NULL == pMem) {
  717. DbgPrintf("Error: Out of Memory!\n");
  718. DebugBreak();
  719. ExitErrMsg(FALSE, "Error: Out of Memory!\n");
  720. }
  721. return pMem;
  722. }
  723. typedef struct _StringListEntry {
  724. LIST_ENTRY ListEntry;
  725. PSTR pStr;
  726. } STRINGLISTENTRY, *PSTRINGLISTENTRY;
  727. VOID
  728. FreeMacroArgsList(PMACROARGSLIST pArgs) {
  729. SIZE_T c;
  730. for(c=0; c < (SIZE_T)pArgs->NumArgs; c++) {
  731. GenHeapFree(pArgs->ArgText[c]);
  732. }
  733. GenHeapFree(pArgs);
  734. }
  735. char *
  736. CArg(
  737. char *pSrc,
  738. PCGENSTATE pCGenState,
  739. PSTR *pBuffer,
  740. BOOL TestExistOnly
  741. )
  742. {
  743. int i;
  744. int ArgNum;
  745. CHAR s[MAX_PATH];
  746. PCHAR pResult;
  747. PMACROARGSLIST pList = pCGenState->pCaseArgsList;
  748. PCHAR pCommandName = TestExistOnly ? szCARGEXIST : szCARG;
  749. if (!pList) {
  750. ExitErrMsg(FALSE, "%s(%d) %s unexpected: no case is currently being applied\n",
  751. TemplateFileName, TemplateLine, pCommandName);
  752. return NULL;
  753. }
  754. if (*pSrc != '(') {
  755. ExitErrMsg(FALSE, "%s(%d) %s Incorrect parameter %s\n",
  756. TemplateFileName, TemplateLine, pCommandName, pSrc);
  757. return NULL;
  758. }
  759. pSrc++;
  760. i = 0;
  761. while ((*pSrc != ')') && (i < sizeof(s)-1)) {
  762. s[i++] = *pSrc++;
  763. }
  764. s[i] = 0;
  765. ArgNum = atoi(s);
  766. pSrc++; // skip ')'
  767. if (ArgNum-- == 0) {
  768. ExitErrMsg(FALSE, "%s(%d) Invalid %s parameter %s\n", TemplateFileName, TemplateLine,
  769. pCommandName, s);
  770. return NULL;
  771. }
  772. if (TestExistOnly) {
  773. pResult = (ArgNum >= pList->NumArgs) ? "0" : "1";
  774. }
  775. else {
  776. if (ArgNum >= pList->NumArgs) {
  777. ExitErrMsg(FALSE, "%s(%d) Case only has %d arguments\n", TemplateFileName, TemplateLine, pList->NumArgs);
  778. return NULL;
  779. }
  780. pResult = pList->ArgText[ArgNum];
  781. }
  782. if (pBuffer != NULL) {
  783. *pBuffer = pResult;
  784. }
  785. else {
  786. CGenerate(pResult, pCGenState);
  787. }
  788. return pSrc;
  789. }
  790. char *ForCase(char *pSrc, PCGENSTATE pCGenState) {
  791. PMACROARGSLIST pCaseArgsListOld;
  792. PLIST_ENTRY pHead, pThis;
  793. char *pch;
  794. char *pExpression;
  795. int OldCaseNumber;
  796. // Are any cases available for application
  797. if (pCGenState->pCaseList == NULL ||
  798. (pCGenState->pCaseList != NULL && IsListEmpty(pCGenState->pCaseList))) {
  799. //Do nothing
  800. return SkipSubExpression(pSrc, NULL);
  801. }
  802. pch = SkipSubExpression(pSrc, &pExpression);
  803. if (pSrc == pch || !pExpression) {
  804. return pch;
  805. }
  806. pSrc = pch;
  807. pCaseArgsListOld = pCGenState->pCaseArgsList;
  808. pHead = pCGenState->pCaseList;
  809. pThis = pHead->Flink;
  810. OldCaseNumber = pCGenState->CaseNumber;
  811. pCGenState->CaseNumber = 0;
  812. do {
  813. pCGenState->pCaseArgsList = CONTAINING_RECORD(pThis,MLLISTENTRY,ListEntry)->pMArgs;
  814. CGenerate(pExpression, pCGenState);
  815. pThis = pThis->Flink;
  816. pCGenState->CaseNumber++;
  817. } while (pThis != pHead );
  818. pCGenState->CaseNumber = OldCaseNumber;
  819. pCGenState->pCaseArgsList = pCaseArgsListOld;
  820. return pSrc;
  821. }
  822. PCHAR
  823. ParseMacroArgs(IN PCHAR pch,
  824. IN SIZE_T maxlen,
  825. OUT PMACROARGSLIST *ppMArgsList
  826. )
  827. {
  828. PMACROARGSLIST pMArgsList = NULL;
  829. LIST_ENTRY ArgsList;
  830. PCHAR pl;
  831. int ArgCount=0;
  832. int ParenDepth=0;
  833. SIZE_T len = 0;
  834. if (maxlen == 0) {
  835. len = MAXUINT_PTR;
  836. }
  837. InitializeListHead(&ArgsList);
  838. if (*pch != '(') {
  839. ExitErrMsg(FALSE, "ParseMacroArgs: Expected to find ( for args list\n");
  840. }
  841. pch++;
  842. ParenDepth++;
  843. len++;
  844. while(ParenDepth > 0) {
  845. pl = pch;
  846. while(1) {
  847. if('\0' == *pl || len > maxlen) {
  848. ExitErrMsg(FALSE, "ParseMacroArgs: Unmatched paren for args list\n");
  849. }
  850. if (*pl == '(') {
  851. ParenDepth++;
  852. }
  853. else if (*pl == ')') {
  854. ParenDepth--;
  855. }
  856. if (ParenDepth == 0 ||
  857. (ParenDepth == 1 && *pl == ',')) {
  858. PSTRINGLISTENTRY pSl;
  859. pSl = CheckHeapAlloc(sizeof(STRINGLISTENTRY));
  860. pSl->pStr = CheckHeapAlloc(pl - pch + 1);
  861. memcpy(pSl->pStr, pch, pl - pch);
  862. pSl->pStr[pl - pch] = '\0';
  863. InsertTailList(&ArgsList, &(pSl->ListEntry));
  864. ArgCount++;
  865. pch = pl + 1;
  866. if (ParenDepth == 0) {
  867. // No more arguments
  868. goto Exit;
  869. }
  870. else {
  871. // Do next argument
  872. break;
  873. }
  874. }
  875. pl++;
  876. }
  877. }
  878. Exit:
  879. pMArgsList = CheckHeapAlloc(sizeof(MACROARGSLIST) + sizeof(LPSTR) * ArgCount);
  880. pMArgsList->NumArgs = ArgCount;
  881. for(ArgCount = 0; ArgCount < pMArgsList->NumArgs; ArgCount++) {
  882. PSTRINGLISTENTRY pSl;
  883. pSl = CONTAINING_RECORD(ArgsList.Flink,STRINGLISTENTRY,ListEntry);
  884. RemoveHeadList(&ArgsList);
  885. pMArgsList->ArgText[ArgCount] = pSl->pStr;
  886. GenHeapFree(pSl);
  887. }
  888. *ppMArgsList = pMArgsList;
  889. return pch;
  890. }
  891. void ExtractServicesTab(char *pch);
  892. /* main
  893. *
  894. * standard win32 base windows entry point
  895. * returns 0 for clean exit, otherwise nonzero for error
  896. *
  897. *
  898. * ExitCode:
  899. * 0 - Clean exit with no Errors
  900. * nonzero - error ocurred
  901. *
  902. */
  903. int __cdecl main(int argc, char **argv)
  904. {
  905. int i;
  906. DWORD dw;
  907. char *pch;
  908. CGENSTATE CGenState;
  909. PLIST_ENTRY Next;
  910. BOOL bUseServicesTab = FALSE;
  911. // init the lists
  912. InitializeListHead(&TypeTempleList);
  913. InitializeListHead(&FailTempleList);
  914. InitializeListHead(&CodeTempleList);
  915. InitializeListHead(&IFuncTempleList);
  916. InitializeListHead(&EFuncTempleList);
  917. InitializeListHead(&EFastTempleList);
  918. InitializeListHead(&CGenerateList);
  919. InitializeListHead(&ExportsList);
  920. InitializeListHead(&DebugStringsList);
  921. InitializeListHead(&MacroList);
  922. NumDebugStringsEntries = 0;
  923. BeginCBI = GetCodeBurstIndex(szCGENBEG); // Preload 'Begin=' as a valid codeburst
  924. SetConsoleCtrlHandler(ConsoleControlHandler, TRUE);
  925. /*try*/ {
  926. /*
  927. * Get cmd line args.
  928. */
  929. i = 0;
  930. while (++i < argc) {
  931. pch = argv[i];
  932. if (*pch == '-' || *pch == '/') {
  933. pch++;
  934. if (_stricmp(pch, "LessTrailingWhitespace") == 0) {
  935. g_fLessTrailingWhitespace = TRUE;
  936. }
  937. else
  938. switch (toupper(*pch)) {
  939. case 'D':
  940. bDebug = TRUE;
  941. setvbuf(stderr, NULL, _IONBF, 0);
  942. break;
  943. case 'F':
  944. bExitClean = FALSE;
  945. break;
  946. case 'T': // template file name
  947. if (!ExtractTemples(pch+1)) {
  948. ExitErrMsg(FALSE, "ExtractTemples failed %s\n", pch);
  949. }
  950. break;
  951. case 'C': //cgenerate "-cOutputFileName[,CppOutputFileName]:TemplateName"
  952. if (!ExtractCGenerate(pch+1)) {
  953. ExitErrMsg(FALSE, "ExtractCGenerate failed %s\n", pch);
  954. }
  955. break;
  956. case 'M': // ppm file name (only 1 expected!)
  957. if (FuncsList) {
  958. ExitErrMsg(FALSE, "ExtractPpm only one Ppm file allowed %s\n", pch);
  959. }
  960. if (!ExtractPpm(pch+1)) {
  961. ExitErrMsg(FALSE, "ExtractPpm failed %s\n", pch);
  962. }
  963. break;
  964. case 'S': //use a services.tab instead of an exports list
  965. bUseServicesTab = TRUE;
  966. ExtractServicesTab(pch+1);
  967. break;
  968. case 'E': // xpt list for exports "-eExportListName"
  969. dw = GetFullPathName(pch+1,
  970. sizeof(XptName) - 1,
  971. XptName,
  972. &XptBaseName
  973. );
  974. if (!dw || dw >= sizeof(XptName) - 1) {
  975. ExitErrMsg(FALSE, "Invalid XptName %s\n", pch);
  976. }
  977. break;
  978. case 'X': // Enable exports from implib, -eXptName assumed
  979. bUseExpListAndImplib = TRUE;
  980. break;
  981. case 'I': // implib file name "-iImplibName"
  982. dw = GetFullPathName(pch+1,
  983. sizeof(ImplibName) - 1,
  984. ImplibName,
  985. &ImplibBaseName
  986. );
  987. if (!dw || dw >= sizeof(ImplibName) - 1) {
  988. ExitErrMsg(FALSE, "Invalid Import Library Name %s\n", pch);
  989. }
  990. break;
  991. case 'L': // Disable fuzzy logic symbol name matching
  992. bNoFuzzyLogic = TRUE;
  993. break;
  994. case 'W': // warn about unthunked structures containing function ptrs
  995. bWarnAboutNestedFuncPtrs = TRUE;
  996. break;
  997. case 'U': // [U]se direction information (__in, __out)
  998. bUseDirection = FALSE; // turn it off
  999. break;
  1000. case 'K': // generate chec[K] file from @Log() macros
  1001. UseLogMacros(pch+1);
  1002. break;
  1003. case 'N': // specify explicit DLL base name
  1004. strncpy(DllBaseName, pch+1, MAX_PATH);
  1005. break;
  1006. case 'G': // ignore function prototype errors for debugging purpose only
  1007. bIgnorePrototypeError = TRUE;
  1008. break;
  1009. default:
  1010. ExitErrMsg(FALSE, "Unrecognized option %s\n", pch);
  1011. }
  1012. }
  1013. else if (*pch) {
  1014. dw = GetFullPathName(pch,
  1015. sizeof(DllName) - 1,
  1016. DllName,
  1017. &DllBaseName
  1018. );
  1019. if (!dw || dw >= sizeof(DllName) - 1) {
  1020. ExitErrMsg(FALSE, "Invalid DllName %s\n", pch);
  1021. }
  1022. }
  1023. }
  1024. if(!bUseServicesTab) {
  1025. //
  1026. // MapView of importlib and dll into memory and
  1027. // set up global variables for easy access
  1028. //
  1029. if (ImplibName[0]) {
  1030. if (!MapViewImplib(ImplibName)) {
  1031. ExitErrMsg(FALSE, "Couldn't open import lib '%s'\n", ImplibName);
  1032. }
  1033. }
  1034. if (DllName[0]) {
  1035. if (!MapViewDll(DllName)) {
  1036. ExitErrMsg(FALSE, "Couldn't open DLL '%s'\n", DllName);
  1037. }
  1038. }
  1039. //
  1040. // Extract exports using dll and implib.
  1041. //
  1042. if (DllName[0] && (!XptName[0] || bUseExpListAndImplib)) {
  1043. // Insist that we have both an implib and a dll.
  1044. if ((DllName[0] && !ImplibName[0]) || (ImplibName[0] && !DllName[0])) {
  1045. ExitErrMsg(FALSE, "DllName or ImplibName missing\n");
  1046. }
  1047. if (!ExtractExports()) {
  1048. ExitErrMsg(FALSE, "Failed to get exports for <%s>\n", DllName);
  1049. }
  1050. }
  1051. //
  1052. // Extract exports from the api list
  1053. //
  1054. if (XptName[0]) {
  1055. if (!ExtractXpt(XptName, DllName)) {
  1056. ExitErrMsg(FALSE, "Failed to get exports for <%s>\n", XptName);
  1057. }
  1058. }
  1059. }
  1060. //
  1061. // Set Internal forwards.
  1062. //
  1063. SetInternalForwards();
  1064. Next = CGenerateList.Flink;
  1065. while (Next != &CGenerateList) {
  1066. memset(&CGenState, 0, sizeof(CGenState));
  1067. CGenState.CGen = CONTAINING_RECORD(Next,CGENERATE,CGenerateEntry);
  1068. ProcessTemple(&CGenState);
  1069. DelOpenFile(CGenState.CGen->fp, NULL);
  1070. fclose(CGenState.CGen->fp);
  1071. Next= Next->Flink;
  1072. }
  1073. }
  1074. /*except(EXCEPTION_EXECUTE_HANDLER) {
  1075. ExitErrMsg(FALSE,
  1076. "ExceptionCode=%x\n",
  1077. GetExceptionCode()
  1078. );
  1079. }*/
  1080. CloseOpenFileList(FALSE);
  1081. return 0;
  1082. }
  1083. int
  1084. GetCodeBurstIndex(
  1085. char *BurstName
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Given a name of a 'foo=' (ie. "foo"), return its index in the array
  1090. of codebursts. If there is no 'foo=' on file, add it.
  1091. Arguments:
  1092. BurstName - name of codeburst to get/add.
  1093. Return Value:
  1094. Index into template->CodeBursts[], or calls ExitErrMsg() on error.
  1095. --*/
  1096. {
  1097. int i;
  1098. int FirstFree = -1;
  1099. if (strcmp(BurstName, "CGenBegin") == 0) {
  1100. // Compatibility: Accept 'CGenBegin' as 'Begin'
  1101. return BeginCBI;
  1102. }
  1103. for (i=0; i<MAX_CODEBURST; ++i) {
  1104. if (CodeBursts[i].Name) {
  1105. if (strcmp(BurstName, CodeBursts[i].Name) == 0) {
  1106. return i;
  1107. }
  1108. } else {
  1109. if (FirstFree == -1) {
  1110. FirstFree = i;
  1111. }
  1112. }
  1113. }
  1114. if (FirstFree == -1) {
  1115. if (TemplateFileName) {
  1116. ExitErrMsg(FALSE,
  1117. "%s(%d) Cannot specify more than %d unique codeburst names (%s)",
  1118. TemplateFileName, TemplateLine,
  1119. MAX_CODEBURST, BurstName
  1120. );
  1121. } else {
  1122. ExitErrMsg(FALSE,
  1123. "Cannot specify more than %d unique codeburst names (%s)",
  1124. MAX_CODEBURST, BurstName
  1125. );
  1126. }
  1127. }
  1128. i = strlen(BurstName)+1;
  1129. CodeBursts[FirstFree].Name = GenHeapAlloc(i);
  1130. if (!CodeBursts[FirstFree].Name) {
  1131. ExitErrMsg(TRUE, "Out of memory in GetCodeBurstIndex");
  1132. }
  1133. memcpy(CodeBursts[FirstFree].Name, BurstName, i);
  1134. return FirstFree;
  1135. }
  1136. int
  1137. GetExistingCodeBurstIndex(
  1138. char *BurstName
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. Given a name of a 'foo=' (ie. "foo"), return its index in the array
  1143. of codebursts. If there is no 'foo=' on file, call ExitErrMsg().
  1144. Arguments:
  1145. BurstName - name of codeburst to get.
  1146. Return Value:
  1147. Index into template->CodeBursts[], or -1 on error.
  1148. --*/
  1149. {
  1150. int i;
  1151. if (strcmp(BurstName, "CGenBegin") == 0) {
  1152. // Compatibility: Accept 'CGenBegin' as 'Begin'
  1153. return BeginCBI;
  1154. }
  1155. for (i=0; i<MAX_CODEBURST; ++i) {
  1156. if (CodeBursts[i].Name) {
  1157. if (strcmp(BurstName, CodeBursts[i].Name) == 0) {
  1158. return i;
  1159. }
  1160. }
  1161. }
  1162. return -1;
  1163. }
  1164. PKNOWNTYPES
  1165. GetApiTypes(
  1166. PEXPORTSDEBUG ExportsDbg
  1167. )
  1168. {
  1169. PKNOWNTYPES ApiTypes;
  1170. char *ExpName;
  1171. char *pch;
  1172. ExpName = ExportsDbg->IntForward ? ExportsDbg->IntForward->ExportName
  1173. : ExportsDbg->ExportName;
  1174. //
  1175. // Look in the FakeFuncsLIst, and the FuncsList.
  1176. //
  1177. ApiTypes = GetNameFromTypesList(&FakeFuncsList, ExpName);
  1178. if (!ApiTypes) {
  1179. ApiTypes = GetNameFromTypesList(FuncsList, ExpName);
  1180. }
  1181. //
  1182. // If export is a decorated name then lets see if we have
  1183. // a func that matches the undecorated name
  1184. //
  1185. if (!ApiTypes) {
  1186. pch = strchr(ExpName, '@');
  1187. if (pch) {
  1188. *pch = '\0';
  1189. ApiTypes = GetNameFromTypesList(&FakeFuncsList, ExpName);
  1190. if (!ApiTypes) {
  1191. ApiTypes = GetNameFromTypesList(FuncsList, ExpName);
  1192. }
  1193. *pch = '@';
  1194. }
  1195. }
  1196. if (!ApiTypes && ExportsDbg->Data) {
  1197. ApiTypes = GetNameFromTypesList(TypeDefsList, "PVOID");
  1198. }
  1199. else
  1200. {
  1201. if (!ApiTypes || !ApiTypes->pfuncinfo) {
  1202. ApiTypes = BuildFakeTypesInfo(ExportsDbg, ApiTypes);
  1203. }
  1204. if (!ApiTypes->pktRet) {
  1205. // Get KnownTypes info for Return Type
  1206. PKNOWNTYPES pkt;
  1207. ResetLexer();
  1208. LexMacroArgs(ApiTypes->FuncRet);
  1209. ConsumeConstVolatileOpt();
  1210. if (ParseTypes(TypeDefsList, NULL, &pkt) == FALSE) {
  1211. CurrentTokenIndex = 0;
  1212. if (ParseTypes(StructsList, NULL, &pkt) == FALSE ) {
  1213. ExitErrMsg(FALSE, "GetApiTypes: Undefined return type %s\n", ApiTypes->FuncRet);
  1214. }
  1215. }
  1216. ApiTypes->pktRet = pkt;
  1217. }
  1218. }
  1219. return ApiTypes;
  1220. }
  1221. /*
  1222. * ProcessTemple
  1223. */
  1224. void ProcessTemple(PCGENSTATE pCGenState)
  1225. {
  1226. PLIST_ENTRY Next;
  1227. PTEMPLES pTemple;
  1228. PTEMPLES pTempleEx;
  1229. pTemple = GetTemplate(&CodeTempleList, pCGenState->CGen->TempleName);
  1230. if (pTemple) {
  1231. fprintf(pCGenState->CGen->fp,
  1232. "%s CodeTemplate:%s\n",
  1233. pTemple->Comment,
  1234. pTemple->Name
  1235. );
  1236. pCGenState->Temple = pTemple;
  1237. ExpandTemple(pCGenState->Temple, pCGenState->CodeBurstIndex, pCGenState);
  1238. } else if (pTemple = GetTemplate(&IFuncTempleList,
  1239. pCGenState->CGen->TempleName
  1240. )) {
  1241. pCGenState->ApiNum = 0;
  1242. Next = ExportsList.Flink;
  1243. while (Next != &ExportsList) {
  1244. BYTE ApiPlatform;
  1245. pCGenState->ExportsDbg = CONTAINING_RECORD(Next,
  1246. EXPORTSDEBUG,
  1247. ExportsDbgEntry
  1248. );
  1249. //
  1250. // Switch this API in or out depending on the platform info
  1251. //
  1252. ApiPlatform = pCGenState->ExportsDbg->ApiPlatform;
  1253. pCGenState->Temple = pTemple;
  1254. PlatformSwitchStart(pCGenState, ApiPlatform);
  1255. pCGenState->ApiTypes = GetApiTypes(pCGenState->ExportsDbg);
  1256. //
  1257. // Use exception template for this api if there is one
  1258. //
  1259. pTempleEx = GetTemplate(&EFuncTempleList,
  1260. pCGenState->ExportsDbg->ExportName
  1261. );
  1262. pCGenState->TempleEx = pTempleEx;
  1263. if (pTempleEx) {
  1264. pCGenState->ExTemplate = TRUE;
  1265. } else {
  1266. pCGenState->ExTemplate = FALSE;
  1267. }
  1268. if (pTempleEx && (pTempleEx->CodeBurst[BeginCBI] || TempleHasNoCodeBursts(pTempleEx))) {
  1269. pCGenState->Temple = pTempleEx;
  1270. fprintf(pCGenState->CGen->fp,
  1271. "%s Func Template:%s\n",
  1272. pTempleEx->Comment,
  1273. pTempleEx->Name
  1274. );
  1275. if (TempleHasNoCodeBursts(pTempleEx)) {
  1276. // skip this API: ex template, but not code at all
  1277. fprintf(pCGenState->CGen->fp,
  1278. "%s *** WARNING *** Excluded Api %s\n",
  1279. pCGenState->Temple->Comment,
  1280. pCGenState->ExportsDbg->ExportName
  1281. );
  1282. goto SkipGen;
  1283. }
  1284. /*
  1285. else if (bIgnorePrototypeError) {
  1286. fprintf(pCGenState->CGen->fp,
  1287. "%s Error:1 Ignoring Api %s\n",
  1288. pCGenState->Temple->Comment,
  1289. pCGenState->ExportsDbg->ExportName
  1290. );
  1291. goto SkipGen;
  1292. }
  1293. */
  1294. } else {
  1295. // no ex template
  1296. pCGenState->Temple = pTemple;
  1297. if (pCGenState->ExportsDbg->Data) {
  1298. // DATA export - skip the API
  1299. fprintf(pCGenState->CGen->fp,
  1300. "%s *** WARNING *** Excluded Data Export %s\n",
  1301. pCGenState->Temple->Comment,
  1302. pCGenState->ExportsDbg->ExportName
  1303. );
  1304. goto SkipGen;
  1305. } else if (!pCGenState->ApiTypes->pfuncinfo) {
  1306. // members unknown - skip the API
  1307. if (bIgnorePrototypeError)
  1308. {
  1309. fprintf(pCGenState->CGen->fp,
  1310. "%s Error:2 Ignoring Api %s\n",
  1311. pCGenState->Temple->Comment,
  1312. pCGenState->ExportsDbg->ExportName
  1313. );
  1314. goto SkipGen;
  1315. }
  1316. else {
  1317. ExitErrMsg(FALSE,
  1318. "API %s has no function prototype - unable to generate code.",
  1319. pCGenState->ExportsDbg->ExportName
  1320. );
  1321. }
  1322. } else if (!iHandleCpp && pCGenState->ExportsDbg->CplusDecoration) {
  1323. // CPP export and we aren't set up for CPP exports
  1324. fprintf(pCGenState->CGen->fp,
  1325. "%s *** WARNING *** Excluding CPP Api: %s\n",
  1326. pCGenState->Temple->Comment,
  1327. pCGenState->ExportsDbg->ExportName
  1328. );
  1329. goto SkipGen;
  1330. }
  1331. }
  1332. //
  1333. // skip this api if:
  1334. // - external forward reference
  1335. // - internal forward which does not define the fn
  1336. //
  1337. //
  1338. if ( (pCGenState->ExportsDbg->ExtForward ||
  1339. (pCGenState->ExportsDbg->IntForward &&
  1340. pCGenState->ExportsDbg->IntForward != pCGenState->ExportsDbg))) {
  1341. fprintf(pCGenState->CGen->fp,
  1342. "%s %s forwarded to %s\n",
  1343. pCGenState->Temple->Comment,
  1344. pCGenState->ExportsDbg->ExportName,
  1345. pCGenState->ExportsDbg->ExtForward
  1346. ? pCGenState->ExportsDbg->ExtForward
  1347. : pCGenState->ExportsDbg->IntForward->ExportName
  1348. );
  1349. if (pTempleEx) {
  1350. fprintf(pCGenState->CGen->fp,
  1351. "%s WARNING: forwarded function has an exception template\n",
  1352. pCGenState->Temple->Comment,
  1353. pTempleEx->Name
  1354. );
  1355. }
  1356. } else { // gen code for this api
  1357. PLIST_ENTRY NextArg;
  1358. PARGSLIST pArgsList;
  1359. BuildArgsList(pTempleEx,
  1360. pCGenState->ApiTypes->pfuncinfo,
  1361. &pCGenState->ExportsDbg->ArgsListHead
  1362. );
  1363. if (GetArgSize(pCGenState->ExportsDbg) < 0) {
  1364. // members unknown - skip the API
  1365. if (bIgnorePrototypeError)
  1366. {
  1367. fprintf(pCGenState->CGen->fp,
  1368. "%s Error:3 Ignoring Api %s\n",
  1369. pCGenState->Temple->Comment,
  1370. pCGenState->ExportsDbg->ExportName
  1371. );
  1372. goto SkipGen;
  1373. }
  1374. else {
  1375. ExitErrMsg(FALSE,
  1376. "API %s has no function prototype - unable to generate code.",
  1377. pCGenState->ExportsDbg->ExportName
  1378. );
  1379. }
  1380. } else {
  1381. ExpandTemple(pCGenState->Temple, BeginCBI, pCGenState);
  1382. //
  1383. // Dump warnings about unthunked parameters which
  1384. // contain nested function pointers.
  1385. //
  1386. if (bWarnAboutNestedFuncPtrs && !pTempleEx) {
  1387. int ArgNum = 1;
  1388. NextArg = pCGenState->ExportsDbg->ArgsListHead.Flink;
  1389. while (NextArg != &pCGenState->ExportsDbg->ArgsListHead) {
  1390. pArgsList = CONTAINING_RECORD(NextArg,
  1391. ARGSLIST,
  1392. ArgumentsEntry
  1393. );
  1394. if (pArgsList->fRequiresThunk) {
  1395. //
  1396. // The argument contained a nested function
  1397. // pointer, and nothing thunked that
  1398. // function pointer. Warn about a potential
  1399. // bug.
  1400. //
  1401. fprintf(pCGenState->CGen->fp,
  1402. "// *** WARNING: Arg %d: type '%s' contains an unthunked function pointer ***\n",
  1403. ArgNum,
  1404. pArgsList->Type
  1405. );
  1406. }
  1407. NextArg = NextArg->Flink;
  1408. ArgNum++;
  1409. }
  1410. }
  1411. //
  1412. // clean up pArgsList->LocalVar and ArgHostName
  1413. //
  1414. NextArg = pCGenState->ExportsDbg->ArgsListHead.Flink;
  1415. while (NextArg != &pCGenState->ExportsDbg->ArgsListHead) {
  1416. pArgsList = CONTAINING_RECORD(NextArg,
  1417. ARGSLIST,
  1418. ArgumentsEntry
  1419. );
  1420. if (pArgsList->ArgLocal) {
  1421. GenHeapFree(pArgsList->ArgLocal);
  1422. pArgsList->ArgLocal = NULL;
  1423. }
  1424. if (pArgsList->HostCastedName) {
  1425. GenHeapFree(pArgsList->HostCastedName);
  1426. pArgsList->HostCastedName = NULL;
  1427. }
  1428. NextArg = NextArg->Flink;
  1429. }
  1430. pCGenState->ApiNum++;
  1431. }
  1432. }
  1433. SkipGen:
  1434. //
  1435. // End switching this API in or out depending on the platform info
  1436. //
  1437. ApiPlatform = pCGenState->ExportsDbg->ApiPlatform;
  1438. PlatformSwitchEnd(pCGenState, ApiPlatform);
  1439. Next= Next->Flink;
  1440. }
  1441. } else {
  1442. ExitErrMsg(FALSE,
  1443. "%s,%s:%s Template undefined\n",
  1444. pCGenState->CGen->FileNameC,
  1445. pCGenState->CGen->FileNameCpp ? pCGenState->CGen->FileNameCpp : "",
  1446. pCGenState->CGen->TempleName
  1447. );
  1448. }
  1449. }
  1450. void
  1451. PlatformSwitchStart(
  1452. PCGENSTATE pCGenState,
  1453. BYTE ApiPlatform
  1454. )
  1455. {
  1456. BOOL fIsAsm;
  1457. if (ApiPlatform == API_ALL) {
  1458. return;
  1459. }
  1460. //
  1461. // Switch this API in or out depending on the platform info
  1462. // 00: don't emit anything
  1463. // 01: emit "== 0x0400"
  1464. // 10: emit "> 0x0400"
  1465. // 11: emit ">= 0x0400"
  1466. //
  1467. if (!pCGenState->Temple || !pCGenState->Temple->Comment) {
  1468. fIsAsm = FALSE;
  1469. } else {
  1470. if (strcmp(pCGenState->Temple->Comment, ";") == 0) {
  1471. fIsAsm = TRUE;
  1472. } else {
  1473. fIsAsm = FALSE;
  1474. }
  1475. }
  1476. if (fIsAsm) {
  1477. fprintf(pCGenState->CGen->fp, "\nif ");
  1478. } else {
  1479. fprintf(pCGenState->CGen->fp, "\n#if ");
  1480. }
  1481. if (ApiPlatform & API_WIN9x) {
  1482. BYTE Plat = (ApiPlatform & API_WIN9x) >> API_SHIFT_WIN9x;
  1483. fprintf(pCGenState->CGen->fp,
  1484. (fIsAsm) ? AsmPlatformSwitches[Plat] : CPlatformSwitches[Plat],
  1485. "_WIN32_WINDOWS"
  1486. );
  1487. }
  1488. if ((ApiPlatform & API_WIN9x) && (ApiPlatform & API_NTx)) {
  1489. // API is on some flavor of Win9x and some NTx flavor
  1490. fprintf(pCGenState->CGen->fp, (fIsAsm) ? " OR " : " || ");
  1491. }
  1492. if (ApiPlatform & API_NTx) {
  1493. BYTE Plat = (ApiPlatform & API_NTx) >> API_SHIFT_NTx;
  1494. fprintf(pCGenState->CGen->fp,
  1495. (fIsAsm) ? AsmPlatformSwitches[Plat] : CPlatformSwitches[Plat],
  1496. "_WIN32_WINNT"
  1497. );
  1498. }
  1499. if (pCGenState->ListCol) {
  1500. WriteListColumn(pCGenState);
  1501. } else {
  1502. fprintf(pCGenState->CGen->fp, "\n");
  1503. }
  1504. }
  1505. void
  1506. PlatformSwitchEnd(
  1507. PCGENSTATE pCGenState,
  1508. BYTE ApiPlatform
  1509. )
  1510. {
  1511. if (ApiPlatform != API_ALL) {
  1512. if (strcmp(pCGenState->Temple->Comment, ";") == 0) {
  1513. fprintf(pCGenState->CGen->fp, "\nendif ; _WIN32_WIN...\n");
  1514. } else {
  1515. fprintf(pCGenState->CGen->fp, "\n#endif // _WIN32_WIN...\n");
  1516. }
  1517. if (pCGenState->ListCol) {
  1518. WriteListColumn(pCGenState);
  1519. } else {
  1520. fprintf(pCGenState->CGen->fp, "\n");
  1521. }
  1522. }
  1523. }
  1524. void
  1525. PlatformSwitchEndTable(
  1526. PCGENSTATE pCGenState,
  1527. BYTE ApiPlatform
  1528. )
  1529. {
  1530. if (ApiPlatform != API_ALL) {
  1531. if (strcmp(pCGenState->Temple->Comment, ";") == 0) {
  1532. fprintf(pCGenState->CGen->fp, "\nendif ; _WIN32_WIN...\n");
  1533. } else {
  1534. fprintf(pCGenState->CGen->fp, "\n#else\n {whInvalidCall, 0, 0},");
  1535. fprintf(pCGenState->CGen->fp, "\n#endif // _WIN32_WIN...\n");
  1536. }
  1537. if (pCGenState->ListCol) {
  1538. WriteListColumn(pCGenState);
  1539. } else {
  1540. fprintf(pCGenState->CGen->fp, "\n");
  1541. }
  1542. }
  1543. }
  1544. /*
  1545. * BuildArgsList
  1546. *
  1547. *
  1548. */
  1549. void BuildArgsList(PTEMPLES pTempleEx, PFUNCINFO funcinfo, PLIST_ENTRY pListHead)
  1550. {
  1551. int i;
  1552. ULONG Size;
  1553. int OffSet=0;
  1554. int ArgOffSet;
  1555. PKNOWNTYPES pkt;
  1556. PARGSLIST pArgsList;
  1557. int NoTypeCount;
  1558. char *HostCastedName;
  1559. if (!IsListEmpty(pListHead)) {
  1560. return;
  1561. }
  1562. if (!pTempleEx) {
  1563. NoTypeCount = 0;
  1564. } else {
  1565. //
  1566. // There is an [EFunc] for this API. Get the count of
  1567. // NoType= entries for the EFunc.
  1568. //
  1569. for (NoTypeCount=0; NoTypeCount<MAX_NOTYPE; ++NoTypeCount) {
  1570. if (!pTempleEx->NoTypes[NoTypeCount]) {
  1571. break;
  1572. }
  1573. }
  1574. }
  1575. while (funcinfo) {
  1576. pkt = GetNameFromTypesList(TypeDefsList, funcinfo->sType);
  1577. if (!pkt) {
  1578. pkt = GetNameFromTypesList(StructsList, funcinfo->sType);
  1579. if (!pkt) {
  1580. ExitErrMsg(FALSE, "Unknown type %s\n", funcinfo->sType);
  1581. }
  1582. }
  1583. //
  1584. // Save the ArgOffSet, and add the args size to the cumulative
  1585. // offset for the next argument.
  1586. //
  1587. // Round up the arg size to the next dword. Assumes intel stack
  1588. // parameter passing conventions, and that all pointers are
  1589. // sizeof(int *) except __ptr64 which are sizeof(PVOID64).
  1590. //
  1591. ArgOffSet = OffSet;
  1592. Size = funcinfo->IndLevel +
  1593. pkt->IndLevel ?
  1594. funcinfo->fIsPtr64 ?
  1595. SIZEOFPOINTER64 : SIZEOFPOINTER : pkt->Size;
  1596. OffSet += ((Size + 3) & ~3) >> 2;
  1597. //
  1598. // Create ARGSLIST entry, and add it to the list
  1599. //
  1600. pArgsList = GenHeapAlloc(sizeof(ARGSLIST));
  1601. if (!pArgsList) {
  1602. ExitErrMsg(TRUE, "bal.\n");
  1603. }
  1604. memset(pArgsList, 0, sizeof(ARGSLIST));
  1605. if(funcinfo->sName == NULL) {
  1606. HostCastedName = GenHeapAlloc(sizeof(szHOSTAPPEND));
  1607. if (NULL == HostCastedName)
  1608. ExitErrMsg(FALSE, "Out of memory in BuildArgsList\n");
  1609. strcpy(HostCastedName, szHOSTAPPEND);
  1610. }
  1611. else {
  1612. HostCastedName = GenHeapAlloc(sizeof(szHOSTAPPEND) + strlen(funcinfo->sName));
  1613. if (NULL == HostCastedName)
  1614. ExitErrMsg(FALSE, "Out of memory in BuildArgsList\n");
  1615. strcpy(HostCastedName, funcinfo->sName);
  1616. strcat(HostCastedName, szHOSTAPPEND);
  1617. }
  1618. pArgsList->pKnownTypes = pkt;
  1619. pArgsList->OffSet = ArgOffSet;
  1620. pArgsList->IndLevel = funcinfo->IndLevel;
  1621. pArgsList->ArgSize = Size;
  1622. pArgsList->IsPtr64 = funcinfo->fIsPtr64;
  1623. pArgsList->Mod = funcinfo->tkPreMod;
  1624. pArgsList->tkDirection = funcinfo->tkDirection;
  1625. pArgsList->SUEOpt = funcinfo->tkSUE;
  1626. pArgsList->Type = funcinfo->sType;
  1627. pArgsList->PostMod = funcinfo->tkPostMod;
  1628. pArgsList->PrePostMod = funcinfo->tkPrePostMod;
  1629. pArgsList->Name = funcinfo->sName;
  1630. pArgsList->HostCastedName = HostCastedName;
  1631. pArgsList->fIsMember = FALSE;
  1632. pArgsList->bIsBitfield = FALSE;
  1633. pArgsList->BitsRequired= 0;
  1634. pArgsList->bIsArray = FALSE;
  1635. pArgsList->ArrayElements=0;
  1636. if (pkt->Flags & BTI_CONTAINSFUNCPTR) {
  1637. //
  1638. // This parameter type is either a function pointer, or
  1639. // a type which contains an embedded function pointer.
  1640. // Something is going to have to thunk it.
  1641. //
  1642. pArgsList->fRequiresThunk = TRUE;
  1643. }
  1644. if (pTempleEx) {
  1645. //
  1646. // There is an [EFunc] for this API. See if this param
  1647. // should have [Types] templates expanded or not.
  1648. //
  1649. for (i=0; i<NoTypeCount; ++i) {
  1650. if (pTempleEx->NoTypes[i] &&
  1651. strcmp(pArgsList->Name, pTempleEx->NoTypes[i]) == 0) {
  1652. //
  1653. // This param is not supposed to have [Types] expanded
  1654. //
  1655. pArgsList->fNoType = TRUE;
  1656. pTempleEx->NoTypes[i] = NULL;
  1657. }
  1658. }
  1659. }
  1660. InsertTailList(pListHead, &pArgsList->ArgumentsEntry);
  1661. //
  1662. // and on to the next argument .....
  1663. //
  1664. funcinfo = funcinfo->pfuncinfoNext;
  1665. }
  1666. if (pTempleEx) {
  1667. //
  1668. // For error reporting, indicate any NoTypes= that did not match
  1669. // a param name
  1670. //
  1671. for (i=0; i<NoTypeCount; ++i) {
  1672. if (pTempleEx->NoTypes[i]) {
  1673. ExitErrMsg(FALSE, "[EFunc] %s(%x) has a 'NoType=%s' which does not correspond to an argument name\n", pTempleEx->Name, pTempleEx, pTempleEx->NoTypes[i]);
  1674. }
  1675. }
  1676. }
  1677. return;
  1678. }
  1679. //
  1680. // return pointer to type of first argument
  1681. char *NArgType(PCGENSTATE pCGenState, char *s, int iLen, char **ppSrc)
  1682. {
  1683. PARGSLIST pArgsList;
  1684. PLIST_ENTRY Next;
  1685. char *pch = s;
  1686. CGENSTATE CGenState;
  1687. int Len, i;
  1688. char *pSrc;
  1689. pSrc = *ppSrc;
  1690. if (*pSrc != '(') {
  1691. ErrMsg("Incorrect NArgType parameter %s\n", pSrc);
  1692. fprintf(pCGenState->CGen->fp, "** ERROR ** Incorrect NArgType parameter %s\n", pSrc);
  1693. return NULL;
  1694. }
  1695. pSrc++;
  1696. i = 0;
  1697. while ((*pSrc != ')') && (i < iLen-1)) {
  1698. s[i++] = *pSrc++;
  1699. }
  1700. s[i] = 0;
  1701. *ppSrc = ++pSrc;
  1702. Len = atoi(s);
  1703. if (Len-- == 0) {
  1704. ErrMsg("Invalid NArgType parameter %s\n", s);
  1705. fprintf(pCGenState->CGen->fp, "** ERROR ** Invalid NArgType parameter %s\n", s);
  1706. return NULL;
  1707. }
  1708. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  1709. fprintf(pCGenState->CGen->fp,
  1710. "\n\t*** ERROR ***\n*** NArgType Missing argument List: %s\n\n",
  1711. pCGenState->ApiTypes->TypeName
  1712. );
  1713. return NULL;
  1714. }
  1715. Next = pCGenState->ExportsDbg->ArgsListHead.Flink;
  1716. // check for void arg list
  1717. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  1718. if (!pArgsList->Name && strcmp(pArgsList->Type, szVARGS)) {
  1719. return NULL;
  1720. }
  1721. CGenState = *pCGenState;
  1722. for (i = 0; (i < Len) && (Next != &CGenState.ExportsDbg->ArgsListHead); i++) {
  1723. Next= Next->Flink;
  1724. }
  1725. if (Next == &CGenState.ExportsDbg->ArgsListHead) {
  1726. ErrMsg("NArgType parameter out of range %d\n", Len);
  1727. fprintf(pCGenState->CGen->fp, "** ERROR ** NArgType parameter out of range %d\n", Len);
  1728. return NULL;
  1729. }
  1730. CGenState.pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  1731. //
  1732. // Copy in the explicit struct/union/enum keyword, if present
  1733. //
  1734. strcat(pch, TokenString[CGenState.pArgsList->SUEOpt]);
  1735. //
  1736. // Copy in the actual typename
  1737. //
  1738. strcpy(pch, CGenState.pArgsList->Type);
  1739. if (CGenState.pArgsList->PrePostMod != TK_NONE) {
  1740. strcat(pch, " ");
  1741. strcat(pch, TokenString[CGenState.pArgsList->PrePostMod]);
  1742. }
  1743. pch = pch + strlen(pch);
  1744. if (CGenState.pArgsList->IndLevel) {
  1745. *pch++ = ' ';
  1746. for (i=0; i<CGenState.pArgsList->IndLevel; ++i) {
  1747. *pch++ = '*';
  1748. }
  1749. }
  1750. *pch = '\0';
  1751. return(s);
  1752. }
  1753. //
  1754. // return pointer to name of first argument
  1755. char *NArgName(PCGENSTATE pCGenState, char *s, int iLen, char **ppSrc)
  1756. {
  1757. PARGSLIST pArgsList;
  1758. PLIST_ENTRY Next;
  1759. char *pch = s;
  1760. CGENSTATE CGenState;
  1761. int Len, i;
  1762. char *pSrc;
  1763. pSrc = *ppSrc;
  1764. if (*pSrc != '(') {
  1765. ErrMsg("Incorrect NArgType parameter %s\n", pSrc);
  1766. fprintf(pCGenState->CGen->fp, "** ERROR ** Incorrect NArgType parameter %s\n", pSrc);
  1767. return(NULL);
  1768. }
  1769. pSrc++;
  1770. i = 0;
  1771. while ((*pSrc != ')') && (i < iLen-1)) {
  1772. s[i++] = *pSrc++;
  1773. }
  1774. s[i] = 0;
  1775. *ppSrc = ++pSrc;
  1776. Len = atoi(s);
  1777. if (Len-- == 0) {
  1778. ErrMsg("Invalid NArgType parameter %s\n", s);
  1779. fprintf(pCGenState->CGen->fp, "** ERROR ** Invalid NArgType parameter %s\n", s);
  1780. return(NULL);
  1781. }
  1782. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  1783. fprintf(pCGenState->CGen->fp,
  1784. "\n\t*** ERROR ***\n*** NArgType Missing argument List: %s\n\n",
  1785. pCGenState->ApiTypes->TypeName
  1786. );
  1787. return(NULL);
  1788. }
  1789. Next = pCGenState->ExportsDbg->ArgsListHead.Flink;
  1790. // check for void arg list
  1791. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  1792. if (!pArgsList->Name && strcmp(pArgsList->Type, szVARGS)) {
  1793. return(NULL);
  1794. }
  1795. CGenState = *pCGenState;
  1796. for (i = 0; (i < Len) && (Next != &CGenState.ExportsDbg->ArgsListHead); i++) {
  1797. Next= Next->Flink;
  1798. }
  1799. if (Next == &CGenState.ExportsDbg->ArgsListHead) {
  1800. ErrMsg("NArgName parameter out of range %d\n", Len);
  1801. fprintf(pCGenState->CGen->fp, "** ERROR ** NArgName parameter out of range %d\n", Len);
  1802. return(NULL);
  1803. }
  1804. CGenState.pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  1805. strcpy(pch, CGenState.pArgsList->Name);
  1806. return(s);
  1807. }
  1808. char *
  1809. MArg(
  1810. char *pSrc,
  1811. PCGENSTATE pCGenState,
  1812. PSTR *pBuffer
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. Expand the n'th argument for the current macro
  1817. Arguments:
  1818. pSrc - pointer to character following 'MArg'
  1819. pCGenState - current code-gen state
  1820. Return Value:
  1821. pointer to character following the end of the macro argument
  1822. --*/
  1823. {
  1824. int i;
  1825. int ArgNum;
  1826. PMACROARGSLIST pList = pCGenState->pMacroArgsList;
  1827. char s[MAX_PATH];
  1828. PMACROARGSLIST OldList;
  1829. if (!pList) {
  1830. ExitErrMsg(FALSE, "%s(%d) MArg unexpected: no macro is currently being expanded\n", TemplateFileName, TemplateLine);
  1831. return NULL;
  1832. }
  1833. if (*pSrc != '(') {
  1834. ExitErrMsg(FALSE, "%s(%d) Incorrect MArg parameter %s\n", TemplateFileName, TemplateLine, pSrc);
  1835. return NULL;
  1836. }
  1837. pSrc++;
  1838. i = 0;
  1839. while ((*pSrc != ')') && (i < sizeof(s)-1)) {
  1840. s[i++] = *pSrc++;
  1841. }
  1842. s[i] = 0;
  1843. ArgNum = atoi(s);
  1844. pSrc++; // skip ')'
  1845. if (ArgNum-- == 0) {
  1846. ExitErrMsg(FALSE, "%s(%d) Invalid MArg parameter %s\n", TemplateFileName, TemplateLine, s);
  1847. return NULL;
  1848. }
  1849. if (ArgNum >= pList->NumArgs) {
  1850. ExitErrMsg(FALSE, "%s(%d) Macro only takes %d arguments\n", TemplateFileName, TemplateLine, pList->NumArgs);
  1851. return NULL;
  1852. }
  1853. if (pBuffer == NULL) {
  1854. OldList = pCGenState->pMacroArgsList;
  1855. pCGenState->pMacroArgsList = MacroStack[--MacroStackTop];
  1856. CGenerate(pList->ArgText[ArgNum], pCGenState);
  1857. MacroStack[MacroStackTop++] = pCGenState->pMacroArgsList;
  1858. pCGenState->pMacroArgsList = OldList;
  1859. }
  1860. else {
  1861. *pBuffer = pList->ArgText[ArgNum];
  1862. }
  1863. return pSrc;
  1864. }
  1865. char *ArgType(char *Buffer, PCGENSTATE pCGenState) {
  1866. char *pch;
  1867. if (pCGenState->pArgsList) {
  1868. int i;
  1869. pch = Buffer;
  1870. if (pCGenState->pArgsList->SUEOpt != TK_NONE) {
  1871. strcpy(pch, TokenString[pCGenState->pArgsList->SUEOpt]);
  1872. strcat(pch, " ");
  1873. pch += strlen(pch);
  1874. }
  1875. strcpy(pch, pCGenState->pArgsList->Type);
  1876. if (pCGenState->pArgsList->PrePostMod != TK_NONE) {
  1877. strcat(pch, " ");
  1878. strcat(pch, TokenString[pCGenState->pArgsList->PrePostMod]);
  1879. }
  1880. pch = pch+strlen(pch);
  1881. if (pCGenState->pArgsList->IndLevel) {
  1882. *pch++ = ' ';
  1883. for (i=0; i<pCGenState->pArgsList->IndLevel; ++i) {
  1884. *pch++ = '*';
  1885. }
  1886. }
  1887. *pch = '\0';
  1888. pch = Buffer;
  1889. return pch;
  1890. }
  1891. else
  1892. return NULL;
  1893. }
  1894. char *UnalignedTag64(char *Buffer, PCGENSTATE pCGenState) {
  1895. //
  1896. // PUT UNALIGNED TAg for interested type like KLPWST KHBITMAP all kernel mode shareable struct
  1897. //
  1898. char CurrArgType[256];
  1899. if ( NULL == ArgType ( CurrArgType, pCGenState))
  1900. return NULL;
  1901. //
  1902. // Now chek the name
  1903. //
  1904. if ( pCGenState->pArgsList->ArgSize == 8 ) {
  1905. //
  1906. // BUGBUG: check if you need special case for KLPWSTR and KHBITMAP
  1907. // if so put more generic form
  1908. //(strncmp ( CurrAgrType, "KLPWSTR ",7) == 0) ||
  1909. //(strncmp ( CurrAgrType, "KHBITMAP ",8) == 0)
  1910. //
  1911. strcpy (Buffer, "*(UNALIGNED ");
  1912. strcat (Buffer, CurrArgType);
  1913. if (strchr(CurrArgType, '*') == NULL )
  1914. strcat ( Buffer, " ");
  1915. strcat (Buffer, "*)&");
  1916. return Buffer;
  1917. }
  1918. return NULL;
  1919. }
  1920. char *ArgHostType(char *Buffer, PCGENSTATE pCGenState) {
  1921. char *pch;
  1922. if (pCGenState->pArgsList) {
  1923. pch = Buffer;
  1924. /*if (pCGenState->pArgsList->SUEOpt != TK_NONE) {
  1925. strcpy(pch, TokenString[pCGenState->pArgsList->SUEOpt]);
  1926. strcat(pch, " ");
  1927. pch += strlen(pch);
  1928. }*/
  1929. if (pCGenState->pArgsList->IndLevel > 0) {
  1930. strcpy(pch, GetHostPointerName(pCGenState->pArgsList->IsPtr64));
  1931. pch += strlen(pch);
  1932. }
  1933. else {
  1934. char Buffer[MAX_PATH];
  1935. strcpy(pch, GetHostTypeName(pCGenState->pArgsList->pKnownTypes, Buffer));
  1936. pch += strlen(pch);
  1937. }
  1938. *pch = '\0';
  1939. pch = Buffer;
  1940. return pch;
  1941. }
  1942. else
  1943. return NULL;
  1944. }
  1945. BOOL IsPointer(PCGENSTATE pCGenState) {
  1946. return (pCGenState->pArgsList->IndLevel > 0) || (pCGenState->pArgsList->pKnownTypes->IndLevel > 0);
  1947. }
  1948. char *ArgTypeInd(char *Buffer, PCGENSTATE pCGenState, BOOL bHostName) {
  1949. CGENSTATE GenStateOld;
  1950. ARGSLIST ArgsListOld;
  1951. KNOWNTYPES KnownTypes;
  1952. PKNOWNTYPES pCurrent;
  1953. int IndLevel;
  1954. char *pch;
  1955. //copy over the old structures before mangaling them
  1956. GenStateOld = *pCGenState;
  1957. ArgsListOld = *(pCGenState->pArgsList);
  1958. KnownTypes = *(pCGenState->pArgsList->pKnownTypes);
  1959. pCGenState->pArgsList->pKnownTypes = &KnownTypes;
  1960. if (pCGenState->pArgsList->IndLevel > 0) {
  1961. IndLevel = pCGenState->pArgsList->IndLevel - 1;
  1962. goto success;
  1963. }
  1964. pCurrent = &KnownTypes;
  1965. IndLevel = pCurrent->IndLevel;
  1966. if (IndLevel == 0) {
  1967. ErrMsg("ArgTypeInd: Tried to get name of type pointed to by %s\n",pCGenState->pArgsList->Name);
  1968. ExitErrMsg(FALSE, "ArgTypeInd: %s is not a pointer!\n", pCGenState->pArgsList->Name);
  1969. }
  1970. while(1) {//chase all the way down to a struct/union/enum or a func_ptr
  1971. PCHAR IndName;
  1972. ASSERT(pCurrent != NULL);
  1973. if (pCurrent->IndLevel == 1 && !bHostName && ((IndName = IsDefinedPtrToPtrDependent(pCurrent->TypeName)) != NULL)) {
  1974. PKNOWNTYPES pkt;
  1975. IndLevel--;
  1976. pkt = GetNameFromTypesList(TypeDefsList, IndName);
  1977. ASSERT(pkt != NULL);
  1978. KnownTypes = *pkt;
  1979. goto success;
  1980. }
  1981. else if (pCurrent->pTypedefBase != NULL) {
  1982. pCurrent = pCurrent->pTypedefBase;
  1983. }
  1984. else {
  1985. //hit a struct/union/enum or func_ptr
  1986. KnownTypes = *pCurrent;
  1987. pCGenState->pArgsList->pStructType = NULL;
  1988. pCGenState->pArgsList->SUEOpt = TK_NONE;
  1989. IndLevel--;
  1990. if (pCurrent->Flags & BTI_NOTDERIVED) {
  1991. pCGenState->pArgsList->SUEOpt = TK_NONE;
  1992. goto success;
  1993. }
  1994. else if(strcmp("struct", KnownTypes.BaseName) == 0) {
  1995. pCGenState->pArgsList->SUEOpt = TK_STRUCT;
  1996. goto success;
  1997. }
  1998. else if(strcmp("union", KnownTypes.BaseName) == 0) {
  1999. pCGenState->pArgsList->SUEOpt = TK_UNION;
  2000. goto success;
  2001. }
  2002. else if(strcmp("enum", KnownTypes.BaseName) == 0) {
  2003. pCGenState->pArgsList->SUEOpt = TK_ENUM;
  2004. goto success;
  2005. }
  2006. else {
  2007. ExitErrMsg(FALSE, "ArgTypeInd: Can't determine what %s is.\n", pCGenState->pArgsList->Name);
  2008. }
  2009. }
  2010. }
  2011. success:
  2012. //fake out the typename and the indirection
  2013. KnownTypes.IndLevel = 0;
  2014. pCGenState->pArgsList->IndLevel = IndLevel;
  2015. pCGenState->pArgsList->Type = KnownTypes.TypeName;
  2016. //Print the mangled type, then restore the old type
  2017. if (bHostName)
  2018. pch = ArgHostType(Buffer, pCGenState);
  2019. else
  2020. pch = ArgType(Buffer, pCGenState);
  2021. *pCGenState = GenStateOld;
  2022. *(pCGenState->pArgsList) = ArgsListOld;
  2023. return pch;
  2024. }
  2025. char *ApiName(char *pSrc, char**pch, char *Buffer, PCGENSTATE pCGenState) {
  2026. char *pTemp;
  2027. strcpy(Buffer, pCGenState->ExportsDbg->ExportName);
  2028. // if ApiName has decoration then truncate it
  2029. pTemp = strchr(Buffer, '@');
  2030. if (pTemp) {
  2031. *pTemp = '\0';
  2032. }
  2033. *pch = Buffer;
  2034. return pSrc;
  2035. }
  2036. char *ApiNameSkip(char *pSrc, char**pch, char *Buffer, PCGENSTATE pCGenState) {
  2037. char *pNewSrc, *pTemp, *pEnd;
  2038. int CharsToSkip;
  2039. pNewSrc = ApiName(pSrc, pch, Buffer, pCGenState);
  2040. pEnd = SkipSubExpression(pNewSrc, NULL);
  2041. if (pNewSrc == pEnd)
  2042. return pNewSrc;
  2043. pTemp = pNewSrc+1;
  2044. CharsToSkip = atoi(pTemp);
  2045. while(**pch != '\0' && CharsToSkip > 0) {
  2046. (*pch)++;
  2047. CharsToSkip--;
  2048. }
  2049. return pEnd;
  2050. }
  2051. BOOL IsPointerToPtrDep(PARGSLIST pArgsList) {
  2052. PKNOWNTYPES pCurrent;
  2053. pCurrent = pArgsList->pKnownTypes;
  2054. if (pArgsList->IndLevel + pCurrent->IndLevel < 1)
  2055. ExitErrMsg(FALSE, "IsPointerToPtrDep: %s is not a pointer\n", pArgsList->Name);
  2056. if (pArgsList->IndLevel + pCurrent->IndLevel > 1) {
  2057. // Since pCurrent->IndLevel is acumulative, this can happen if and
  2058. // only if this type or one of its base types is a pointer to
  2059. // another pointer. This case is defined to be pointer dependent.
  2060. return TRUE;
  2061. }
  2062. // At this point, either pArgsList->IndLevel == 1 and pCurrent->IndLevel == 0
  2063. // or pArgsList->IndLevel == 0 and pCurrent->IndLevel = 1.
  2064. // First check if this type is defined to be a pointer to a pointer dependent type.
  2065. // If not, defererence the pointer by walking through typedefs until pCurrent->IndLevel = 0
  2066. // Note that multiple levels of pointers are no longer possible.
  2067. if(IsDefinedPtrToPtrDependent(pCurrent->TypeName)) {
  2068. return TRUE;
  2069. }
  2070. while(pCurrent->IndLevel != 0) {
  2071. // Check if this type is one of the special types used
  2072. // between sortpp and genthnk.
  2073. if (pCurrent->Flags & BTI_NOTDERIVED)
  2074. return FALSE;
  2075. // Assert that this type is not a struct, union, or enum.
  2076. // This shouldn't happen because sortpp should store
  2077. // these with an indlevel of 0.
  2078. ASSERT(strcmp(pCurrent->BaseName, "struct") != 0);
  2079. ASSERT(strcmp(pCurrent->BaseName, "union") != 0);
  2080. ASSERT(strcmp(pCurrent->BaseName, "enum") != 0);
  2081. // Check if this type is a function pointer. If it is,
  2082. // return FALSE since they are arbitrarly defined to not
  2083. // be pointer dependent. This may be changed check if any
  2084. // of the arguments to the function pointer are pointer dependent.
  2085. if (strcmp(pCurrent->BaseName, "()") == 0)
  2086. return FALSE;
  2087. // Get the base typedef.
  2088. pCurrent = pCurrent->pTypedefBase;
  2089. }
  2090. // Now that the pointer has been dereferenced, test if
  2091. // this type is pointer dependent.
  2092. return (pCurrent->Flags & BTI_POINTERDEP) != 0;
  2093. }
  2094. char *TestIfPointerToPtrDep(char *pSrc, PCGENSTATE pCGenState, PCHAR pch) {
  2095. PCHAR pEnd;
  2096. PMACROARGSLIST pMArgsList;
  2097. ARGSLIST ArgsList;
  2098. CHAR TypeName[MAX_PATH];
  2099. SIZE_T BytesReturned;
  2100. pEnd = SkipSubExpression(pSrc, NULL);
  2101. if (pSrc == pEnd) {
  2102. ExitErrMsg(FALSE, "TestIfPointerToPtrDep: exactly 1 argument is required.\n");
  2103. }
  2104. ParseMacroArgs(pSrc, pEnd - pSrc, &pMArgsList);
  2105. if (pMArgsList->NumArgs != 1) {
  2106. ExitErrMsg(FALSE, "IncludeRetTypes: exactly 1 argument is required.\n");
  2107. }
  2108. CGenerateEx(pMArgsList->ArgText[0], pCGenState, TypeName, MAX_PATH, &BytesReturned);
  2109. SetArgListToTypeForArg(&ArgsList, &ArgsList, TypeName);
  2110. if(IsPointerToPtrDep(&ArgsList)) {
  2111. strcpy(pch, "1");
  2112. }
  2113. else {
  2114. strcpy(pch, "0");
  2115. }
  2116. FreeMacroArgsList(pMArgsList);
  2117. return pEnd;
  2118. }
  2119. BOOL IsPtrDep(PARGSLIST pArgsList) {
  2120. //This is a pointer to something(ptr dep.)
  2121. if (pArgsList->IndLevel > 0)
  2122. return TRUE;
  2123. return pArgsList->pKnownTypes->Flags & ( BTI_POINTERDEP | BTI_INT64DEP );
  2124. }
  2125. BOOL IsInt64DepUnion(PCGENSTATE pCGenState) {
  2126. char Buff[256];
  2127. Buff[0]=0;
  2128. ArgTypeInd( Buff, pCGenState, FALSE);
  2129. // make exception for union _ULARGE_INTEGER
  2130. if (strncmp(Buff, "union _ULARGE_INTEGER", sizeof ("union _ULARGE_INTEGER")) == 0 )
  2131. return TRUE; //IsPointerToPtrDep ( pArgsList );
  2132. if (strncmp(Buff, "union _LARGE_INTEGER", sizeof ("union _LARGE_INTEGER")) == 0 )
  2133. return TRUE; //IsPointerToPtrDep ( pArgsList );
  2134. return FALSE; //pArgsList->pKnownTypes->Flags & BTI_INT64DEP;
  2135. }
  2136. void DoIndent(PCGENSTATE pCGenState) {
  2137. int i;
  2138. for(i=IndentLevel, OutputColumn = 1; i > 0; i--,OutputColumn++) {
  2139. if (fputc(' ', pCGenState->CGen->fp) != ' ')
  2140. ExitErrMsg(TRUE, "fputc %s\n", pCGenState->CGen->FileNameC);
  2141. OutputColumn++;
  2142. }
  2143. }
  2144. char * CGeneratePrintChar(char *pch, PCGENSTATE pCGenState) {
  2145. if (!bStripNewline) {
  2146. if('\n' == *pch) {
  2147. //bFirstCharHit = FALSE;
  2148. OutputColumn = 0; //will be incremented to 1
  2149. }
  2150. goto PrintIt;
  2151. }
  2152. else {
  2153. if (*pch == '\n')
  2154. goto SkipIt;
  2155. if (!bFirstCharHit) {
  2156. if(!isspace(*pch)) {
  2157. DoIndent(pCGenState);
  2158. bFirstCharHit = TRUE;
  2159. goto PrintIt;
  2160. }
  2161. else
  2162. goto SkipIt;
  2163. }
  2164. else
  2165. goto PrintIt;
  2166. }
  2167. PrintIt:
  2168. if (fputc(*pch, pCGenState->CGen->fp) != *pch)
  2169. goto PrintError;
  2170. OutputColumn++;
  2171. SkipIt:
  2172. return pch + 1;
  2173. PrintError:
  2174. ExitErrMsg(TRUE, "fputc %s\n", pCGenState->CGen->FileNameC);
  2175. return NULL;
  2176. }
  2177. char *CGenerate(char *pSrc, PCGENSTATE pCGenState) {
  2178. return CGenerateEx(pSrc, pCGenState, NULL, 0, NULL);
  2179. }
  2180. /*
  2181. * CGenerate
  2182. *
  2183. */
  2184. char *CGenerateEx(char *pSrc, PCGENSTATE pCGenState, char *OutBuffer, SIZE_T MaxLen, SIZE_T *BytesReturned)
  2185. {
  2186. FILE **pfp = &pCGenState->CGen->fp;
  2187. char *pch;
  2188. size_t Len;
  2189. char Buffer[MAX_PATH*4];
  2190. char *BufferPos = NULL;
  2191. if (OutBuffer != NULL) {
  2192. BufferPos = OutBuffer;
  2193. *BytesReturned = 0;
  2194. }
  2195. while (*pSrc) {
  2196. if (OutBuffer != NULL && MaxLen == 0) {
  2197. ExitErrMsg(FALSE, "Out of buffer space!\n");
  2198. }
  2199. if (*pSrc != '@') {
  2200. if (OutBuffer != NULL) {
  2201. *BufferPos++ = *pSrc++;
  2202. *BytesReturned += 1;
  2203. MaxLen--;
  2204. }
  2205. else {
  2206. pSrc = CGeneratePrintChar(pSrc, pCGenState);
  2207. }
  2208. }
  2209. else if (*(pSrc + 1) == '@') {
  2210. pSrc++;
  2211. if (OutBuffer != NULL) {
  2212. *BufferPos++ = *pSrc++;
  2213. *BytesReturned += 1;
  2214. MaxLen--;
  2215. }
  2216. else {
  2217. pSrc = CGeneratePrintChar(pSrc, pCGenState);
  2218. }
  2219. }
  2220. else {
  2221. #define ELSE(f) \
  2222. if ( *pSrc == '@' && \
  2223. !strncmp(pSrc+1, szELSE, sizeof(szELSE) - 1)) { \
  2224. pSrc += sizeof(szELSE) - 1+1; \
  2225. pSrc = WriteMore(pSrc, pCGenState, !(f)); \
  2226. }
  2227. pch = NULL;
  2228. memset(Buffer, 0, sizeof(Buffer));
  2229. pSrc++; //skip the @ is the command name
  2230. if(bStripNewline && !bFirstCharHit) {
  2231. OutputColumn = 1 + IndentLevel;
  2232. }
  2233. if (!strncmp(pSrc, szNL, sizeof(szNL) - 1)) {
  2234. pSrc += sizeof(szNL) - 1;
  2235. if (fputc('\n', *pfp) != '\n')
  2236. ExitErrMsg(TRUE, "fputc %s\n", pCGenState->CGen->FileNameC);
  2237. OutputColumn = 1;
  2238. bFirstCharHit = FALSE;
  2239. }
  2240. else if (!strncmp(pSrc, szINDENT, sizeof(szINDENT) - 1)) {
  2241. int OldIndent;
  2242. pSrc += sizeof(szINDENT) - 1;
  2243. OldIndent = IndentLevel;
  2244. IndentLevel += INDENTSIZE;
  2245. pSrc = WriteMore(pSrc, pCGenState, TRUE);
  2246. IndentLevel = OldIndent;
  2247. }
  2248. else if (!strncmp(pSrc, szNOFORMAT, sizeof(szNOFORMAT) - 1)) {
  2249. BOOL bOldStripNewline;
  2250. pSrc += sizeof(szNOFORMAT) - 1;
  2251. bOldStripNewline = bStripNewline;
  2252. bStripNewline = FALSE;
  2253. pSrc = WriteMore(pSrc, pCGenState, TRUE);
  2254. bStripNewline = bOldStripNewline;
  2255. }
  2256. else if (!strncmp(pSrc, szTEMPLATE, sizeof(szTEMPLATE) - 1)) {
  2257. pSrc += sizeof(szTEMPLATE) - 1;
  2258. pSrc = IncludeTemplate(pSrc, pCGenState);
  2259. }
  2260. else if (!strncmp(pSrc, szAPILIST, sizeof(szAPILIST) - 1)) {
  2261. pSrc += sizeof(szAPILIST) - 1;
  2262. pSrc = ListApis(pSrc, pCGenState, FALSE);
  2263. }
  2264. else if (!strncmp(pSrc, szAPINAMESKIP, sizeof(szAPINAMESKIP) -1 )) {
  2265. pSrc += sizeof(szAPINAMESKIP) - 1;
  2266. pSrc = ApiNameSkip(pSrc, &pch, Buffer, pCGenState);
  2267. }
  2268. else if (!strncmp(pSrc, szAPINAME, sizeof(szAPINAME) - 1)) {
  2269. pSrc += sizeof(szAPINAME) - 1;
  2270. pSrc = ApiName(pSrc, &pch, Buffer, pCGenState);
  2271. }
  2272. else if (!strncmp(pSrc, szAPIFORWARD, sizeof(szAPIFORWARD) - 1)) {
  2273. pSrc += sizeof(szAPIFORWARD) - 1;
  2274. if (pCGenState->ExportsDbg->IntForward) {
  2275. strcpy(Buffer, szINTFORWARD);
  2276. strcpy(Buffer + sizeof(szINTFORWARD) - 1,
  2277. pCGenState->ExportsDbg->IntForward->ExportName
  2278. );
  2279. }
  2280. else {
  2281. strcpy(Buffer, pCGenState->ExportsDbg->ExportName);
  2282. }
  2283. // if ApiName has decoration then truncate it
  2284. pch = strchr(Buffer, '@');
  2285. if (pch) {
  2286. *pch = '\0';
  2287. }
  2288. pch = Buffer;
  2289. }
  2290. else if (!strncmp(pSrc, szAPINUM, sizeof(szAPINUM) - 1)) {
  2291. _itoa(pCGenState->ApiNum, Buffer, 10);
  2292. pch = Buffer;
  2293. pSrc += sizeof(szAPINUM) - 1;
  2294. }
  2295. else if (!strncmp(pSrc, szAPIFNRET, sizeof(szAPIFNRET) - 1)) {
  2296. if (pCGenState->ApiTypes) {
  2297. pch = pCGenState->ApiTypes->FuncRet;
  2298. }
  2299. pSrc += sizeof(szAPIFNRET) - 1;
  2300. }
  2301. else if (!strncmp(pSrc, szAPIDECLSPEC, sizeof(szAPIDECLSPEC) - 1)) {
  2302. BOOL b = pCGenState->ApiTypes && (pCGenState->ApiTypes->Flags & BTI_DLLEXPORT);
  2303. pSrc += sizeof(szAPIDECLSPEC) - 1;
  2304. pSrc = WriteMore(pSrc, pCGenState, b);
  2305. }
  2306. else if (!strncmp(pSrc, szAPIFNMOD, sizeof(szAPIFNMOD) - 1)) {
  2307. if (pCGenState->ApiTypes) {
  2308. pch = pCGenState->ApiTypes->FuncMod;
  2309. }
  2310. pSrc += sizeof(szAPIFNMOD) - 1;
  2311. }
  2312. else if (!strncmp(pSrc, szAPIMORE, sizeof(szAPIMORE) - 1)) {
  2313. pSrc += sizeof(szAPIMORE) - 1;
  2314. pSrc = WriteMore(pSrc, pCGenState, pCGenState->MoreApis);
  2315. }
  2316. else if (!strncmp(pSrc, szIFAPIRET, sizeof(szIFAPIRET) - 1)) {
  2317. BOOL fResult = FALSE;
  2318. pSrc += sizeof(szIFAPIRET) - 1;
  2319. pSrc = IfApiRet(pSrc, pCGenState, &fResult);
  2320. ELSE(fResult);
  2321. }
  2322. else if (!strncmp(pSrc, szDOESAPIRETURNVOID, sizeof(szDOESAPIRETURNVOID) - 1)) {
  2323. BOOL fResult = FALSE;
  2324. pSrc += sizeof(szDOESAPIRETURNVOID) - 1;
  2325. pSrc = DoesApiReturnVoid(pSrc, pCGenState, &fResult);
  2326. WriteBoolean(Buffer, fResult);
  2327. pch = Buffer;
  2328. }
  2329. else if (!strncmp(pSrc, szIFISMEMBER, sizeof(szIFISMEMBER) - 1)) {
  2330. pSrc += sizeof(szIFISMEMBER) - 1;
  2331. pSrc = WriteMore(pSrc, pCGenState, pCGenState->pArgsList->fIsMember);
  2332. }
  2333. else if (!strncmp(pSrc, szIFNISMEMBER, sizeof(szIFNISMEMBER) - 1)) {
  2334. pSrc += sizeof(szIFNISMEMBER) - 1;
  2335. pSrc = WriteMore(pSrc, pCGenState, !(pCGenState->pArgsList->fIsMember));
  2336. }
  2337. else if (!strncmp(pSrc, szIFISBITFIELD, sizeof(szIFISBITFIELD) - 1)) {
  2338. pSrc += sizeof(szIFISBITFIELD) - 1;
  2339. pSrc = WriteMore(pSrc, pCGenState, pCGenState->pArgsList->bIsBitfield);
  2340. }
  2341. else if (!strncmp(pSrc, szIFNISBITFIELD, sizeof(szIFNISBITFIELD) - 1)) {
  2342. pSrc += sizeof(szIFNISBITFIELD) - 1;
  2343. pSrc = WriteMore(pSrc, pCGenState, !(pCGenState->pArgsList->bIsBitfield));
  2344. }
  2345. else if (!strncmp(pSrc, szIFISARRAY, sizeof(szIFISARRAY) - 1)) {
  2346. pSrc += sizeof(szIFISARRAY) - 1;
  2347. pSrc = WriteMore(pSrc, pCGenState, pCGenState->pArgsList->bIsArray);
  2348. }
  2349. else if (!strncmp(pSrc, szIFNISARRAY, sizeof(szIFNISARRAY) - 1)) {
  2350. pSrc += sizeof(szIFNISARRAY) - 1;
  2351. pSrc = WriteMore(pSrc, pCGenState, !(pCGenState->pArgsList->bIsArray));
  2352. }
  2353. else if (!strncmp(pSrc, szARGARRAYELEMENTS, sizeof(szARGARRAYELEMENTS) - 1)) {
  2354. pSrc += sizeof(szARGARRAYELEMENTS) - 1;
  2355. _itoa((int)(pCGenState->pArgsList->ArrayElements), Buffer, 10);
  2356. pch = Buffer;
  2357. }
  2358. else if (!strncmp(pSrc, szIFPOINTERTOPTRDEP, sizeof(szIFPOINTERTOPTRDEP) -1 )) {
  2359. pSrc += sizeof(szIFPOINTERTOPTRDEP) - 1;
  2360. pSrc = WriteMore(pSrc, pCGenState, IsPointerToPtrDep(pCGenState->pArgsList));
  2361. }
  2362. else if (!strncmp(pSrc, szIFNPOINTERTOPTRDEP, sizeof(szIFNPOINTERTOPTRDEP) -1 )) {
  2363. pSrc += sizeof(szIFNPOINTERTOPTRDEP) - 1;
  2364. pSrc = WriteMore(pSrc, pCGenState, !IsPointerToPtrDep(pCGenState->pArgsList));
  2365. }
  2366. else if (!strncmp(pSrc, szISPOINTERTOPTRDEP, sizeof(szISPOINTERTOPTRDEP) -1 )) {
  2367. pSrc += sizeof(szISPOINTERTOPTRDEP) - 1;
  2368. pch = Buffer;
  2369. pSrc = TestIfPointerToPtrDep(pSrc, pCGenState, pch);
  2370. }
  2371. else if (!strncmp(pSrc, szIFPTRDEP, sizeof(szIFPTRDEP) -1 )) {
  2372. pSrc += sizeof(szIFPTRDEP) - 1;
  2373. pSrc = WriteMore(pSrc, pCGenState, IsPtrDep(pCGenState->pArgsList));
  2374. }
  2375. else if (!strncmp(pSrc, szIFNPTRDEP, sizeof(szIFNPTRDEP) -1 )) {
  2376. pSrc += sizeof(szIFNPTRDEP) - 1;
  2377. pSrc = WriteMore(pSrc, pCGenState, !IsPtrDep(pCGenState->pArgsList));
  2378. }
  2379. else if (!strncmp(pSrc, szIFINT64DEPUNION, sizeof(szIFINT64DEPUNION) -1 )) {
  2380. pSrc += sizeof(szIFINT64DEPUNION) - 1;
  2381. pSrc = WriteMore(pSrc, pCGenState, IsInt64DepUnion(pCGenState));
  2382. }
  2383. else if (!strncmp(pSrc, szIFNINT64DEPUNION, sizeof(szIFNINT64DEPUNION) -1 )) {
  2384. pSrc += sizeof(szIFNINT64DEPUNION) - 1;
  2385. pSrc = WriteMore(pSrc, pCGenState, !IsInt64DepUnion(pCGenState));
  2386. }
  2387. else if (!strncmp(pSrc, szIFAPICODE, sizeof(szIFAPICODE) - 1)) {
  2388. BOOL fResult = FALSE;
  2389. pSrc += sizeof(szIFAPICODE) - 1;
  2390. pSrc = IfApiCode(pSrc, pCGenState, &fResult);
  2391. ELSE(fResult);
  2392. }
  2393. else if (!strncmp(pSrc, szFASTCALL, sizeof(szFASTCALL) - 1)) {
  2394. pSrc += sizeof(szFASTCALL) - 1;
  2395. pSrc = WriteMore(pSrc, pCGenState, IsFastCall(pCGenState));
  2396. }
  2397. else if (!strncmp(pSrc, szSLOWCALL, sizeof(szSLOWCALL) - 1)) {
  2398. pSrc += sizeof(szSLOWCALL) - 1;
  2399. pSrc = WriteMore(pSrc, pCGenState, !IsFastCall(pCGenState));
  2400. }
  2401. else if (!strncmp(pSrc, szFASTX2NMETH, sizeof(szFASTX2NMETH) - 1)) {
  2402. pSrc += sizeof(szFASTX2NMETH) - 1;
  2403. pSrc = WriteMore(pSrc, pCGenState, GetX2NMethodType(pCGenState) == FASTX2NMETHOD);
  2404. }
  2405. else if (!strncmp(pSrc, szSLOWX2NMETH, sizeof(szSLOWX2NMETH) - 1)) {
  2406. pSrc += sizeof(szSLOWX2NMETH) - 1;
  2407. pSrc = WriteMore(pSrc, pCGenState, GetX2NMethodType(pCGenState) == SLOWX2NMETHOD);
  2408. }
  2409. else if (!strncmp(pSrc, szFATX2NMETH, sizeof(szFATX2NMETH) - 1)) {
  2410. pSrc += sizeof(szFATX2NMETH) - 1;
  2411. pSrc = WriteMore(pSrc, pCGenState, GetX2NMethodType(pCGenState) == FATX2NMETHOD);
  2412. }
  2413. else if (!strncmp(pSrc, szMETHODNUMBER, sizeof(szMETHODNUMBER) - 1)) {
  2414. pSrc += sizeof(szMETHODNUMBER) - 1;
  2415. _itoa(pCGenState->ExportsDbg->MethodNumber, Buffer, 10);
  2416. pch = Buffer;
  2417. }
  2418. else if (!strncmp(pSrc, szIFARGS, sizeof(szIFARGS) - 1)) {
  2419. BOOL fResult = FALSE;
  2420. pSrc += sizeof(szIFARGS) - 1;
  2421. pSrc = IfArgs(pSrc, pCGenState, &fResult);
  2422. ELSE(fResult);
  2423. }
  2424. else if (!strncmp(pSrc, szFUNCARGNUM, sizeof(szFUNCARGNUM) - 1)) {
  2425. pSrc += sizeof(szFUNCARGNUM) - 1;
  2426. _itoa(GetFuncArgNum(pCGenState), Buffer, 10);
  2427. pch = Buffer;
  2428. }
  2429. else if (!strncmp(pSrc, szRETSIZE, sizeof(szRETSIZE) - 1)) {
  2430. pSrc += sizeof(szRETSIZE) - 1;
  2431. _itoa(GetRetSize(pCGenState), Buffer, 10);
  2432. pch = Buffer;
  2433. }
  2434. else if (!strncmp(pSrc, szARGSIZE, sizeof(szARGSIZE) - 1)) {
  2435. pSrc += sizeof(szARGSIZE) - 1;
  2436. _itoa(GetArgSize(pCGenState->ExportsDbg), Buffer, 10);
  2437. pch = Buffer;
  2438. }
  2439. else if (!strncmp(pSrc, szFORCASE, sizeof(szFORCASE) - 1)) {
  2440. pSrc += sizeof(szFORCASE) - 1;
  2441. pSrc = ForCase(pSrc, pCGenState);
  2442. }
  2443. else if (!strncmp(pSrc, szCARGEXIST, sizeof(szCARGEXIST) - 1)) {
  2444. pSrc += sizeof(szCARGEXIST) - 1;
  2445. if (OutBuffer != NULL) {
  2446. pSrc = CArg(pSrc, pCGenState, &pch, TRUE);
  2447. }
  2448. else {
  2449. pSrc = CArg(pSrc, pCGenState, NULL, TRUE);
  2450. }
  2451. }
  2452. else if (!strncmp(pSrc, szCARG, sizeof(szCARG) - 1)) {
  2453. pSrc += sizeof(szCARG) - 1;
  2454. if (OutBuffer != NULL) {
  2455. pSrc = CArg(pSrc, pCGenState, &pch, FALSE);
  2456. }
  2457. else {
  2458. pSrc = CArg(pSrc, pCGenState, NULL, FALSE);
  2459. }
  2460. }
  2461. else if (!strncmp(pSrc, szCNUMBER, sizeof(szCNUMBER) - 1)) {
  2462. pSrc += sizeof(szCNUMBER) - 1;
  2463. _itoa(pCGenState->CaseNumber, Buffer, 10);
  2464. pch = Buffer;
  2465. }
  2466. else if (!strncmp(pSrc, szARGLIST, sizeof(szARGLIST) - 1)) {
  2467. pSrc += sizeof(szARGLIST) - 1;
  2468. if (pCGenState->ApiTypes) {
  2469. pSrc = ListArgs(pSrc, pCGenState, TRUE);
  2470. }
  2471. }
  2472. else if (!strncmp(pSrc, szNARGTYPE, sizeof(szNARGTYPE) - 1)) {
  2473. pSrc += sizeof(szNARGTYPE) - 1;
  2474. pch = NArgType(pCGenState, Buffer, sizeof(Buffer), &pSrc);
  2475. }
  2476. else if (!strncmp(pSrc, szNARGNAME, sizeof(szNARGNAME) - 1)) {
  2477. pSrc += sizeof(szNARGNAME) - 1;
  2478. pch = NArgName(pCGenState, Buffer, sizeof(Buffer), &pSrc);
  2479. }
  2480. else if (!strncmp(pSrc, szMARG, sizeof(szMARG) - 1)) {
  2481. pSrc += sizeof(szMARG) - 1;
  2482. if (OutBuffer != NULL) {
  2483. pSrc = MArg(pSrc, pCGenState, &pch);
  2484. }
  2485. else {
  2486. pSrc = MArg(pSrc, pCGenState, NULL);
  2487. }
  2488. }
  2489. else if (!strncmp(pSrc, szFORCETYPE, sizeof(szFORCETYPE) - 1)) {
  2490. pSrc += sizeof(szFORCETYPE) - 1;
  2491. pSrc = ForceTypeExpand( pSrc, pCGenState);
  2492. }
  2493. else if (!strncmp(pSrc, szMEMBERTYPES, sizeof(szMEMBERTYPES) - 1)) {
  2494. pSrc += sizeof(szMEMBERTYPES) - 1;
  2495. pSrc = MemberTypes( pSrc, pCGenState, FALSE);
  2496. }
  2497. else if (!strncmp(pSrc, szBTOTMEMBERTYPES, sizeof(szBTOTMEMBERTYPES) - 1)) {
  2498. pSrc += sizeof(szBTOTMEMBERTYPES) - 1;
  2499. pSrc = MemberTypes( pSrc, pCGenState, TRUE);
  2500. }
  2501. else if (!strncmp(pSrc, szLOG, sizeof(szLOG) - 1)) {
  2502. pSrc += sizeof(szLOG) - 1;
  2503. pSrc = UpdateLog(pSrc, pCGenState);
  2504. }
  2505. else if (!strncmp(pSrc, szIFRETTYPE, sizeof(szIFRETTYPE) - 1)) {
  2506. BOOL fResult = FALSE;
  2507. pSrc += sizeof(szIFRETTYPE) - 1;
  2508. pSrc = IfRetType(pSrc, pCGenState, &fResult);
  2509. ELSE(fResult);
  2510. }
  2511. else if (!strncmp(pSrc, szIFNOTRETTYPE, sizeof(szIFNOTRETTYPE) - 1)) {
  2512. pSrc += sizeof(szIFNOTRETTYPE) - 1;
  2513. pSrc = IfNotRetType(pSrc, pCGenState);
  2514. }
  2515. else if (!strncmp(pSrc, szARGMOD, sizeof(szARGMOD) - 1)) {
  2516. pSrc += sizeof(szARGMOD) - 1;
  2517. if (pCGenState->pArgsList) {
  2518. pch = TokenString[pCGenState->pArgsList->Mod];
  2519. }
  2520. }
  2521. else if (!strncmp(pSrc, szARGPOSTMOD, sizeof(szARGPOSTMOD) - 1)) {
  2522. pSrc += sizeof(szARGPOSTMOD) - 1;
  2523. if (pCGenState->pArgsList) {
  2524. pch = TokenString[pCGenState->pArgsList->PostMod];
  2525. }
  2526. }
  2527. else if (!strncmp(pSrc, szARGTYPEIND, sizeof(szARGTYPEIND) - 1)) {
  2528. pSrc += sizeof(szARGTYPEIND) - 1;
  2529. pch = ArgTypeInd(Buffer, pCGenState, FALSE);
  2530. }
  2531. else if (!strncmp(pSrc, szARGHOSTTYPEIND, sizeof(szARGHOSTTYPEIND) - 1)) {
  2532. pSrc += sizeof(szARGHOSTTYPEIND) - 1;
  2533. pch = ArgTypeInd(Buffer, pCGenState, TRUE);
  2534. }
  2535. else if (!strncmp(pSrc, szARGHOSTTYPE, sizeof(szARGHOSTTYPE) -1 )) {
  2536. pSrc += sizeof(szARGHOSTTYPE) - 1;
  2537. pch = ArgHostType(Buffer, pCGenState);
  2538. }
  2539. else if (!strncmp(pSrc, szARGTYPE, sizeof(szARGTYPE) - 1)) {
  2540. pSrc += sizeof(szARGTYPE) - 1;
  2541. pch = ArgType(Buffer, pCGenState);
  2542. }
  2543. else if (!strncmp(pSrc, szUNALIGNEDTAG64, sizeof(szUNALIGNEDTAG64) - 1)) {
  2544. pSrc += sizeof(szUNALIGNEDTAG64) - 1;
  2545. pch = UnalignedTag64(Buffer, pCGenState);
  2546. }
  2547. else if (!strncmp(pSrc, szARGNAME, sizeof(szARGNAME) - 1)) {
  2548. if (pCGenState->pArgsList) {
  2549. pch = pCGenState->pArgsList->Name;
  2550. if (!pch) {
  2551. pch = "";
  2552. }
  2553. }
  2554. pSrc += sizeof(szARGNAME) - 1;
  2555. }
  2556. else if (!strncmp(pSrc, szARGNAMEHOSTCASTED, sizeof(szARGNAMEHOSTCASTED) - 1)) {
  2557. if (pCGenState->pArgsList) {
  2558. pch = pCGenState->pArgsList->HostCastedName;
  2559. if (!pch) {
  2560. if (pCGenState->pArgsList->Name == NULL)
  2561. pch = "";
  2562. else
  2563. pch = pCGenState->pArgsList->Name;
  2564. }
  2565. }
  2566. pSrc += sizeof(szARGNAMEHOSTCASTED) - 1;
  2567. }
  2568. else if (!strncmp(pSrc, szARGVAL, sizeof(szARGVAL) - 1)) {
  2569. if (pCGenState->pArgsList) {
  2570. strcpy(Buffer, pCGenState->pArgsList->Name);
  2571. // replace all occurrences of '->' by '__'
  2572. // and '.', '*', ')', and '(' by '_'
  2573. pch = Buffer;
  2574. while (*pch) {
  2575. if (*pch == '.' || *pch == ')' || *pch == '(' || *pch == '*')
  2576. *pch = '_';
  2577. else if (*pch == '-' && *(pch+1) == '>') {
  2578. *pch = '_';
  2579. *(pch+1) = '_';
  2580. pch++;
  2581. }
  2582. pch++;
  2583. }
  2584. pch = Buffer;
  2585. } else {
  2586. pch = "";
  2587. }
  2588. pSrc += sizeof(szARGVAL) - 1;
  2589. }
  2590. else if (!strncmp(pSrc, szARGOFF, sizeof(szARGOFF) - 1)) {
  2591. pSrc += sizeof(szARGOFF) - 1;
  2592. if (pCGenState->pArgsList) {
  2593. _itoa(pCGenState->pArgsList->OffSet, Buffer, 10);
  2594. pch = Buffer;
  2595. }
  2596. }
  2597. else if (!strncmp(pSrc, szARGADDR, sizeof(szARGADDR) - 1)) {
  2598. pSrc += sizeof(szARGADDR) - 1;
  2599. if (pCGenState->pArgsList) {
  2600. if (pCGenState->pArgsList->ArgLocal) {
  2601. pch = Buffer;
  2602. *pch = '&';
  2603. strcpy(pch+1, pCGenState->pArgsList->ArgLocal);
  2604. pSrc = SkipSubExpression(pSrc, NULL); }
  2605. else {
  2606. pch = Buffer;
  2607. pSrc = WriteArgAddr(pSrc,
  2608. pCGenState,
  2609. pch,
  2610. sizeof(Buffer)-1
  2611. );
  2612. }
  2613. }
  2614. }
  2615. else if (!strncmp(pSrc, szADDRARGSLIST, sizeof(szADDRARGSLIST) - 1)) {
  2616. pSrc += sizeof(szADDRARGSLIST) - 1;
  2617. pch = GetAddrFirstArg(pCGenState, Buffer, sizeof(Buffer) - 1);
  2618. }
  2619. else if (!strncmp(pSrc, szARGLOCAL, sizeof(szARGLOCAL) - 1)) {
  2620. pSrc += sizeof(szARGLOCAL) - 1;
  2621. if (pCGenState->pArgsList) {
  2622. pch = Buffer;
  2623. if (!WriteArgLocal(pCGenState, pch, sizeof(Buffer)-1)) {
  2624. ExitErrMsg(FALSE, "CGenerate failed\n");
  2625. }
  2626. }
  2627. }
  2628. else if (!strncmp(pSrc, szARGMORE, sizeof(szARGMORE) - 1)) {
  2629. pSrc += sizeof(szARGMORE) - 1;
  2630. pSrc = WriteMore(pSrc,
  2631. pCGenState,
  2632. pCGenState->pArgsList &&
  2633. pCGenState->pArgsList->ArgumentsEntry.Flink
  2634. != &pCGenState->ExportsDbg->ArgsListHead
  2635. );
  2636. }
  2637. else if (!strncmp(pSrc, szTYPES, sizeof(szTYPES) - 1)) {
  2638. pSrc += sizeof(szTYPES) - 1;
  2639. pSrc = IncludeTypes(pSrc, pCGenState, FALSE);
  2640. }
  2641. else if (!strncmp(pSrc, szRTOLTYPES, sizeof(szRTOLTYPES) - 1)) {
  2642. pSrc += sizeof(szRTOLTYPES) - 1;
  2643. pSrc = IncludeTypes(pSrc, pCGenState, TRUE);
  2644. }
  2645. else if (!strncmp(pSrc, szRETTYPE, sizeof(szRETTYPE) - 1)) {
  2646. pSrc += sizeof(szRETTYPE) - 1;
  2647. pSrc = IncludeRetType(pSrc, pCGenState);
  2648. }
  2649. else if (!strncmp(pSrc, szEXPORTLIST, sizeof(szEXPORTLIST) - 1)) {
  2650. pSrc += sizeof(szEXPORTLIST) - 1;
  2651. pSrc = ListApis(pSrc, pCGenState, TRUE);
  2652. }
  2653. else if (!strncmp(pSrc, szEXPNAME, sizeof(szEXPNAME) - 1)) {
  2654. pSrc += sizeof(szEXPNAME) - 1;
  2655. pch = pCGenState->ExportsDbg->ExportName;
  2656. }
  2657. else if (!strncmp(pSrc, szIFEXPFORWARD, sizeof(szIFEXPFORWARD) - 1)) {
  2658. pSrc += sizeof(szIFEXPFORWARD) - 1;
  2659. pch = GetAltExportName(Buffer, pCGenState, sizeof(Buffer) - 1);
  2660. }
  2661. else if (!strncmp(pSrc, szIFORDINALS, sizeof(szIFORDINALS) - 1)) {
  2662. pSrc += sizeof(szIFORDINALS) - 1;
  2663. if (pCGenState->ExportsDbg &&
  2664. (pCGenState->ExportsDbg->Ordinal & 0x80000000))
  2665. {
  2666. pch = Buffer;
  2667. *pch = '@';
  2668. _itoa(IMPORDINAL(pCGenState->ExportsDbg->Ordinal),
  2669. pch + 1,
  2670. 10
  2671. );
  2672. }
  2673. }
  2674. else if (!strncmp(pSrc, szLISTCOL, sizeof(szLISTCOL) - 1)) {
  2675. pSrc += sizeof(szLISTCOL) - 1;
  2676. pCGenState->ListCol = OutputColumn;
  2677. }
  2678. else if (!strncmp(pSrc, szDLLNAME, sizeof(szDLLNAME) - 1)) {
  2679. Len = CopyToken(Buffer, DllBaseName, sizeof(Buffer) - 1);
  2680. if (Len >= sizeof(Buffer) - 1) {
  2681. ExitErrMsg(FALSE, "OverFlow %s\n", pSrc);
  2682. }
  2683. pch = Buffer;
  2684. pSrc += sizeof(szDLLNAME) - 1;
  2685. }
  2686. else if (!strncmp(pSrc, szXPTNAME, sizeof(szXPTNAME) - 1)) {
  2687. Len = CopyToken(Buffer, XptBaseName, sizeof(Buffer) - 1);
  2688. if (Len >= sizeof(Buffer) - 1) {
  2689. ExitErrMsg(FALSE, "OverFlow %s\n", pSrc);
  2690. }
  2691. pch = Buffer;
  2692. pSrc += sizeof(szXPTNAME) - 1;
  2693. }
  2694. else if (!strncmp(pSrc, szDLLTARGET, sizeof(szDLLTARGET) - 1)) {
  2695. Len = CopyToken(Buffer, pCGenState->CGen->FileBaseNameC, sizeof(Buffer) - 1);
  2696. if (Len >= sizeof(Buffer) - 1) {
  2697. ExitErrMsg(FALSE, "Overflow %s\n", pSrc);
  2698. }
  2699. pch = Buffer;
  2700. pSrc += sizeof(szDLLTARGET) - 1;
  2701. }
  2702. else if (!strncmp(pSrc, szAPIUNKNOWN, sizeof(szAPIUNKNOWN) - 1)) {
  2703. pSrc += sizeof(szAPIUNKNOWN) - 1;
  2704. pSrc = WriteMore(pSrc,
  2705. pCGenState,
  2706. pCGenState->ExportsDbg->UnKnownApi
  2707. );
  2708. }
  2709. else if (!strncmp(pSrc, szAPINODECL, sizeof(szAPINODECL) - 1)) {
  2710. pSrc += sizeof(szAPINODECL) - 1;
  2711. pSrc = WriteMore(pSrc,
  2712. pCGenState,
  2713. pCGenState->ExportsDbg->UnKnownApi == 1
  2714. );
  2715. }
  2716. else if (!strncmp(pSrc, szISAPIDECLARED, sizeof(szISAPIDECLARED) - 1)) {
  2717. pSrc += sizeof(szISAPIDECLARED) - 1;
  2718. WriteBoolean(Buffer, pCGenState->ExportsDbg->UnKnownApi == 0);
  2719. pch = Buffer;
  2720. }
  2721. else if (!strncmp(pSrc, szAPISTRINGS, sizeof(szAPISTRINGS) - 1)) {
  2722. pSrc += sizeof(szAPISTRINGS) - 1;
  2723. if (pCGenState->ApiTypes) {
  2724. ApiStrings(pCGenState);
  2725. }
  2726. }
  2727. else if (!strncmp(pSrc, szDBGSINDEX, sizeof(szDBGSINDEX) - 1)) {
  2728. char *pExpression, *pFree;
  2729. int Index;
  2730. pSrc += sizeof(szDBGSINDEX) - 1;
  2731. pch = pSrc;
  2732. pSrc = SkipSubExpression(pch, &pFree);
  2733. if (pSrc != pch) {
  2734. if (!pFree && pCGenState->pArgsList ) {
  2735. pExpression = pCGenState->pArgsList->Type;
  2736. }
  2737. else {
  2738. pExpression = pFree;
  2739. }
  2740. Index = GetFuncIndex(pCGenState, pExpression);
  2741. if (Index == -1) {
  2742. ExitErrMsg(FALSE, "DebugsIndex unknown! %s\n", pch);
  2743. }
  2744. _itoa(Index, Buffer, 10);
  2745. pch = Buffer;
  2746. if (pFree) {
  2747. GenHeapFree(pFree);
  2748. }
  2749. }
  2750. else {
  2751. pch = NULL;
  2752. }
  2753. }
  2754. else if (!strncmp(pSrc, szDBGSLIST, sizeof(szDBGSLIST) - 1)) {
  2755. pSrc += sizeof(szDBGSLIST) - 1;
  2756. pSrc = ListDbgs(pSrc, pCGenState);
  2757. }
  2758. else if (!strncmp(pSrc, szDBGSSTRINGS, sizeof(szDBGSSTRINGS) - 1)) {
  2759. pSrc += sizeof(szDBGSSTRINGS) - 1;
  2760. WriteDbgsStrings(pSrc, pCGenState);
  2761. }
  2762. else if (!strncmp(pSrc, szDBGSMORE, sizeof(szDBGSMORE) - 1)) {
  2763. pSrc += sizeof(szDBGSMORE) - 1;
  2764. pSrc = WriteMore(pSrc, pCGenState, pCGenState->MoreApis);
  2765. }
  2766. else if (!strncmp(pSrc, szOFFSET, sizeof(szOFFSET) - 1)) {
  2767. pSrc += sizeof(szOFFSET) - 1;
  2768. pSrc = GetOffSet(pSrc, Buffer);
  2769. pch = Buffer;
  2770. }
  2771. else if (!strncmp(pSrc, szCPPEXPORT, sizeof(szCPPEXPORT) - 1)) {
  2772. pSrc += sizeof(szCPPEXPORT) - 1;
  2773. pSrc = WriteMore(pSrc,
  2774. pCGenState,
  2775. iHandleCpp > 0 && pCGenState->ExportsDbg->CplusDecoration
  2776. );
  2777. }
  2778. else if (!strncmp(pSrc, szCEXPORT, sizeof(szCEXPORT) - 1)) {
  2779. pSrc += sizeof(szCEXPORT) - 1;
  2780. pSrc = WriteMore(pSrc,
  2781. pCGenState,
  2782. !(iHandleCpp > 0 && pCGenState->ExportsDbg->CplusDecoration)
  2783. );
  2784. }
  2785. else if (!strncmp(pSrc, szCPPOUTPUT, sizeof(szCPPOUTPUT) - 1)) {
  2786. pSrc += sizeof(szCPPOUTPUT) - 1;
  2787. if (pCGenState->CGen->FileNameCpp != NULL) {
  2788. pCGenState->CGen->fp = pCGenState->CGen->fpCpp;
  2789. }
  2790. }
  2791. else if (!strncmp(pSrc, szCOUTPUT, sizeof(szCOUTPUT) - 1)) {
  2792. pSrc += sizeof(szCOUTPUT) - 1;
  2793. pCGenState->CGen->fp = pCGenState->CGen->fpC;
  2794. }
  2795. else if (!strncmp(pSrc, szIF, sizeof(szIF) - 1)) {
  2796. BOOLEAN result;
  2797. pSrc += sizeof(szIF) - 1;
  2798. pSrc = ExtractBoolean1(pSrc, pCGenState, &result);
  2799. pSrc = WriteMore(pSrc, pCGenState, result );
  2800. ELSE(result);
  2801. }
  2802. else if (!strncmp(pSrc, szELSE, sizeof(szELSE) - 1)) {
  2803. ExitErrMsg ( FALSE, "@Else not immediately following @If" );
  2804. }
  2805. else if (!strncmp(pSrc, szOR, sizeof(szOR) - 1)) {
  2806. BOOLEAN result1, result2;
  2807. pSrc += sizeof(szOR) - 1;
  2808. pSrc = ExtractBoolean2(pSrc, pCGenState, &result1, &result2);
  2809. WriteBoolean ( Buffer, result1 || result2 );
  2810. pch = Buffer;
  2811. }
  2812. else if (!strncmp(pSrc, szAND, sizeof(szAND) - 1)) {
  2813. BOOLEAN result1, result2;
  2814. pSrc += sizeof(szAND) - 1;
  2815. pSrc = ExtractBoolean2(pSrc, pCGenState, &result1, &result2);
  2816. WriteBoolean ( Buffer, result1 && result2 );
  2817. pch = Buffer;
  2818. }
  2819. else if (!strncmp(pSrc, szNOT, sizeof(szNOT) - 1)) {
  2820. BOOLEAN result1;
  2821. pSrc += sizeof(szNOT) - 1;
  2822. pSrc = ExtractBoolean1(pSrc, pCGenState, &result1);
  2823. WriteBoolean ( Buffer, !result1);
  2824. pch = Buffer;
  2825. }
  2826. else if (!strncmp(pSrc, szISINTFORWARD, sizeof(szISINTFORWARD) - 1)) {
  2827. pSrc += sizeof(szISINTFORWARD) - 1;
  2828. pSrc = WriteMore(pSrc,
  2829. pCGenState,
  2830. pCGenState->ExportsDbg->IntForward != NULL
  2831. );
  2832. }
  2833. else if (!strncmp(pSrc, szISNOTINTFORWARD, sizeof(szISNOTINTFORWARD) - 1)) {
  2834. pSrc += sizeof(szISNOTINTFORWARD) - 1;
  2835. pSrc = WriteMore(pSrc,
  2836. pCGenState,
  2837. pCGenState->ExportsDbg->IntForward == NULL
  2838. );
  2839. }
  2840. else {
  2841. //
  2842. // See if this is an '@macroname'
  2843. //
  2844. char MacroName[MAX_PATH];
  2845. char *p = MacroName;
  2846. char *pIn = pSrc;
  2847. SIZE_T Bytes;
  2848. while (isalnum(*pIn)) {
  2849. *p++ = *pIn++;
  2850. }
  2851. *p = '\0';
  2852. if (ExpandMacro(MacroName, pCGenState, &pIn, BufferPos, MaxLen, &Bytes)) {
  2853. if (OutBuffer != NULL) {
  2854. Bytes--; // subtract off terminating zero.
  2855. BufferPos += Bytes;
  2856. MaxLen -= Bytes;
  2857. *BytesReturned += Bytes;
  2858. }
  2859. pSrc = pIn;
  2860. } else {
  2861. ExitErrMsg(FALSE, "%s(%d) Unknown keyword '@%s'", TemplateFileName, TemplateLine, MacroName);
  2862. }
  2863. }
  2864. if (pch) {
  2865. if (OutBuffer != NULL) {
  2866. SIZE_T Bytes;
  2867. CGenerateEx(pch, pCGenState, BufferPos, MaxLen, &Bytes);
  2868. Bytes--; // subtract off terminating zero.
  2869. BufferPos += Bytes;
  2870. MaxLen -= Bytes;
  2871. *BytesReturned += Bytes;
  2872. }
  2873. else {
  2874. while (*pch)
  2875. pch = CGeneratePrintChar(pch, pCGenState);
  2876. }
  2877. }
  2878. }
  2879. }
  2880. if (OutBuffer != NULL) {
  2881. if(MaxLen == 0) {
  2882. ExitErrMsg(FALSE, "Out of Buffer space!\n");
  2883. }
  2884. *BufferPos = '\0';
  2885. *BytesReturned += 1;
  2886. }
  2887. return pSrc;
  2888. }
  2889. int GetMemberOffset(char *sTypeName, char *sMemberName)
  2890. {
  2891. PKNOWNTYPES pkt = NULL;
  2892. PMEMBERINFO pmi;
  2893. int i;
  2894. //
  2895. // This is the same as running the lexer on a single identifier...
  2896. //
  2897. Tokens[0].TokenType = TK_IDENTIFIER;
  2898. Tokens[0].Name = sTypeName;
  2899. Tokens[1].TokenType = TK_EOS;
  2900. CurrentTokenIndex = 0;
  2901. if (ParseTypes(TypeDefsList, NULL, &pkt) && pkt != NULL) {
  2902. pkt = GetBasicType(pkt->BaseName, TypeDefsList, StructsList);
  2903. } else {
  2904. CurrentTokenIndex = 0;
  2905. ParseTypes(StructsList, NULL, &pkt);
  2906. }
  2907. if (pkt == NULL) {
  2908. ExitErrMsg(FALSE,
  2909. "GetOffSet: Unknown Type %s\n",
  2910. sTypeName
  2911. );
  2912. }
  2913. pmi = pkt->pmeminfo;
  2914. while (pmi) {
  2915. if (!pmi->sName) {
  2916. //
  2917. // Found a nameless member. See if the member name we're
  2918. // looking for is a member of this nameless member.
  2919. //
  2920. // ie. typedef struct { int bar; } FOO;
  2921. //
  2922. // typedef struct TEST {
  2923. // union {
  2924. // int i;
  2925. // FOO;
  2926. // }
  2927. // } test;
  2928. //
  2929. // GetOffset(TEST, bar) will recurse when pmi points
  2930. // at the memberinfo for the nameless member 'FOO'.
  2931. //
  2932. i = GetMemberOffset(pmi->sType, sMemberName);
  2933. if (i != -1) {
  2934. return i;
  2935. }
  2936. } else if (!strcmp(pmi->sName, sMemberName)) {
  2937. return pmi->dwOffset;
  2938. }
  2939. pmi = pmi->pmeminfoNext;
  2940. }
  2941. return -1;
  2942. }
  2943. char *
  2944. GetOffSet(
  2945. char *pSrc,
  2946. char *Buffer
  2947. )
  2948. {
  2949. char *pOrg = pSrc;
  2950. char *pch;
  2951. int Len;
  2952. char TypeName[MAX_PATH];
  2953. char MemberName[MAX_PATH];
  2954. if (*pSrc != '(') {
  2955. ExitErrMsg(TRUE, "GetOffset: Invalid %s\n", pSrc);
  2956. return NULL;
  2957. }
  2958. while (IsSeparator(*pSrc)) {
  2959. pSrc = GetNextToken(pSrc);
  2960. if (!*pSrc || *pSrc == ')') {
  2961. ExitErrMsg(TRUE, "GetOffset: Invalid %s\n", pOrg);
  2962. return NULL;
  2963. }
  2964. }
  2965. pch = TypeName;
  2966. Len = sizeof(TypeName)-1;
  2967. while ((*pSrc != ',') && (*pSrc != 0)) {
  2968. if (!--Len) {
  2969. *pch = '\0';
  2970. ExitErrMsg(TRUE, "GetOffset: Overflow %s\n", TypeName);
  2971. return NULL;
  2972. }
  2973. *pch++ = *pSrc++;
  2974. }
  2975. *pch = '\0';
  2976. while (IsSeparator(*pSrc)) {
  2977. pSrc = GetNextToken(pSrc);
  2978. if (!*pSrc || *pSrc == ')') {
  2979. ExitErrMsg(TRUE, "GetOffset: Invalid %s\n", pOrg);
  2980. return NULL;
  2981. }
  2982. }
  2983. pch = MemberName;
  2984. Len = sizeof(MemberName)-1;
  2985. while (!IsSeparator(*pSrc)) {
  2986. if (!--Len) {
  2987. *pch = '\0';
  2988. ExitErrMsg(TRUE, "GetOffset: Overflow %s\n", MemberName);
  2989. return NULL;
  2990. }
  2991. *pch++ = *pSrc++;
  2992. }
  2993. *pch = '\0';
  2994. while (*pSrc && *pSrc++ != ')') {
  2995. ;
  2996. }
  2997. Len = GetMemberOffset(TypeName, MemberName);
  2998. if (Len < 0) {
  2999. ExitErrMsg(FALSE,
  3000. "GetOffSet: Unknown Member %s.%s\n",
  3001. TypeName,
  3002. MemberName
  3003. );
  3004. return NULL;
  3005. }
  3006. _ltoa(Len, Buffer, 16);
  3007. return(pSrc);
  3008. }
  3009. /*
  3010. * GetRetSize
  3011. *
  3012. */
  3013. int GetRetSize(PCGENSTATE pCGenState)
  3014. {
  3015. PKNOWNTYPES pkt;
  3016. int RetSize;
  3017. if (!pCGenState->ApiTypes) {
  3018. fprintf(pCGenState->CGen->fp,
  3019. "\n\t*** ERROR ***\n*** GetRetSize: No Api defined\n\n"
  3020. );
  3021. return -1;
  3022. }
  3023. // Get KnownTypes info for Return Type. Can't use the ApiTypes->pktRet
  3024. // cache as ParseIndirection() needs the state of the parse.
  3025. ResetLexer();
  3026. LexMacroArgs(pCGenState->ApiTypes->FuncRet);
  3027. ConsumeConstVolatileOpt();
  3028. if (ParseTypes(TypeDefsList, NULL, &pkt) == FALSE) {
  3029. CurrentTokenIndex = 0;
  3030. if (ParseTypes(StructsList, NULL, &pkt) == FALSE ) {
  3031. fprintf(pCGenState->CGen->fp,
  3032. "\n\t*** ERROR ***\n*** GetRetSize: Undefind Type %s\n\n",
  3033. pCGenState->ApiTypes->FuncRet
  3034. );
  3035. return -1;
  3036. }
  3037. }
  3038. if (pCGenState->ApiTypes->RetIndLevel) {
  3039. RetSize = SIZEOFPOINTER;
  3040. } else {
  3041. RetSize = pkt->Size;
  3042. }
  3043. return RetSize;
  3044. }
  3045. /*
  3046. * GetArgSize
  3047. *
  3048. */
  3049. int GetArgSize(PEXPORTSDEBUG ExportDebug)
  3050. {
  3051. PARGSLIST pArgsList;
  3052. PLIST_ENTRY Next;
  3053. int Total = 0;
  3054. int ArgSize;
  3055. if (IsListEmpty(&ExportDebug->ArgsListHead)) {
  3056. return -1;
  3057. }
  3058. if (ExportDebug->ArgsSize >= 0) {
  3059. return ExportDebug->ArgsSize;
  3060. }
  3061. if (ExportDebug->IntForward && ExportDebug->IntForward->ArgsSize >= 0) {
  3062. ExportDebug->ArgsSize = ExportDebug->IntForward->ArgsSize;
  3063. return ExportDebug->ArgsSize;
  3064. }
  3065. Next = ExportDebug->ArgsListHead.Flink;
  3066. // check for void arg list
  3067. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  3068. if (!pArgsList->Name && strcmp(pArgsList->Type, szVARGS)) {
  3069. return 0;
  3070. }
  3071. do {
  3072. pArgsList = CONTAINING_RECORD(Next,ARGSLIST, ArgumentsEntry);
  3073. ArgSize = (pArgsList->ArgSize + 3) & ~3;
  3074. Total += ArgSize;
  3075. Next= Next->Flink;
  3076. } while (Next != &ExportDebug->ArgsListHead);
  3077. ExportDebug->ArgsSize = Total;
  3078. if (ExportDebug->IntForward) {
  3079. ExportDebug->IntForward->ArgsSize = Total;
  3080. }
  3081. return Total;
  3082. }
  3083. /*
  3084. * ApiStrings
  3085. *
  3086. */
  3087. void ApiStrings(PCGENSTATE pCGenState)
  3088. {
  3089. FILE *fp = pCGenState->CGen->fp;
  3090. PLIST_ENTRY Next;
  3091. PARGSLIST pArgsList;
  3092. PKNOWNTYPES pkt;
  3093. int ArgSize;
  3094. char *pRet;
  3095. char BaseName[MAX_PATH];
  3096. char *c;
  3097. // copy in the DLL name and whack off the extension
  3098. strcpy(BaseName, DllBaseName);
  3099. c = strchr(BaseName, '.');
  3100. if (c) {
  3101. *c = '\0';
  3102. }
  3103. //
  3104. // Write the ApiName <"ApiName", ">
  3105. //
  3106. fprintf(fp, "\"%s!%s\", \"", BaseName, pCGenState->ExportsDbg->ExportName);
  3107. //
  3108. // Write out the Args <Arg1 %x, ArgN %x>
  3109. //
  3110. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  3111. fprintf(fp,
  3112. "\n\t*** ERROR ***\n*** ArgFormat Missing argument List: %s\n\n",
  3113. pCGenState->ApiTypes->TypeName
  3114. );
  3115. return;
  3116. }
  3117. Next = pCGenState->ExportsDbg->ArgsListHead.Flink;
  3118. do {
  3119. pArgsList = CONTAINING_RECORD(Next,ARGSLIST, ArgumentsEntry);
  3120. // check for void arg list
  3121. if (!pArgsList->Name) {
  3122. break;
  3123. }
  3124. fprintf(fp, "%s %s ",
  3125. pArgsList->pKnownTypes->TypeName,
  3126. pArgsList->Name
  3127. );
  3128. // check for vargs
  3129. if (!strcmp(pArgsList->Name, szVARGS)) {
  3130. break;
  3131. }
  3132. ArgSize = pArgsList->ArgSize;
  3133. while (ArgSize > 0) {
  3134. ArgSize -= sizeof(int);
  3135. fprintf(fp,
  3136. "%s%s",
  3137. "%x",
  3138. ArgSize > 0 ? "." : ""
  3139. );
  3140. }
  3141. Next= Next->Flink;
  3142. if (Next != &pCGenState->ExportsDbg->ArgsListHead) {
  3143. fputc(',', fp);
  3144. }
  3145. } while (Next != &pCGenState->ExportsDbg->ArgsListHead);
  3146. //
  3147. // Write out Return Type <", "RetType %x">
  3148. //
  3149. pRet = pCGenState->ApiTypes->FuncRet;
  3150. fprintf(fp, "\", \"%s ", pRet);
  3151. ResetLexer();
  3152. LexMacroArgs(pRet);
  3153. ConsumeConstVolatileOpt();
  3154. // Get Known Types for size of Return Type
  3155. if (ParseTypes(TypeDefsList, NULL, &pkt) == FALSE) {
  3156. CurrentTokenIndex = 0;
  3157. if (ParseTypes(StructsList, NULL, &pkt) == FALSE) {
  3158. fprintf(pCGenState->CGen->fp,
  3159. "\n\t*** ERROR ***\n*** GetRetSize: Undefind Type %s\n\n",
  3160. pCGenState->ApiTypes->FuncRet
  3161. );
  3162. return;
  3163. }
  3164. }
  3165. ArgSize = pkt->Size;
  3166. ParseIndirection(NULL, &ArgSize, NULL, NULL, NULL);
  3167. while (ArgSize > 0) {
  3168. ArgSize -= sizeof(int);
  3169. fprintf(fp,
  3170. "%s%s",
  3171. "%x",
  3172. ArgSize > 0 ? "." : ""
  3173. );
  3174. }
  3175. fprintf(fp, "\"");
  3176. }
  3177. char *
  3178. GetAddrFirstArg(
  3179. PCGENSTATE pCGenState,
  3180. char *Buffer,
  3181. int BuffLen)
  3182. {
  3183. PLIST_ENTRY pFirstEntry;
  3184. PARGSLIST pArgsList;
  3185. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  3186. return "NULL";
  3187. }
  3188. pFirstEntry = pCGenState->ExportsDbg->ArgsListHead.Flink;
  3189. pArgsList = CONTAINING_RECORD(pFirstEntry, ARGSLIST, ArgumentsEntry);
  3190. if (!pArgsList->Name) {
  3191. return "NULL";
  3192. }
  3193. Buffer[0] = '&';
  3194. BuffLen--;
  3195. if ((int)strlen(pArgsList->Name) > BuffLen) {
  3196. ExitErrMsg(TRUE, "gafa: Overflow %s\n", pArgsList->Name);
  3197. }
  3198. strcpy(&Buffer[1], pArgsList->Name);
  3199. return Buffer;
  3200. }
  3201. /*
  3202. * IfArgs
  3203. *
  3204. */
  3205. char *IfArgs(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult)
  3206. {
  3207. PARGSLIST pArgsList;
  3208. PLIST_ENTRY pFirstEntry;
  3209. PKNOWNTYPES pkt;
  3210. *pfResult = TRUE;
  3211. // skip empty list,
  3212. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  3213. *pfResult = FALSE;
  3214. }
  3215. // check for void arg list
  3216. else {
  3217. pFirstEntry = pCGenState->ExportsDbg->ArgsListHead.Flink;
  3218. pArgsList = CONTAINING_RECORD(pFirstEntry, ARGSLIST, ArgumentsEntry);
  3219. if (!pArgsList->Name) {
  3220. pkt = GetNameFromTypesList(TypeDefsList, pArgsList->Type);
  3221. if (!pkt) {
  3222. pkt = GetNameFromTypesList(StructsList, pArgsList->Type);
  3223. }
  3224. if (!pkt) {
  3225. ExitErrMsg(FALSE,
  3226. "ifArgs: Unknown Type %s\n",
  3227. pArgsList->Type
  3228. );
  3229. }
  3230. if (!pkt->IndLevel && !strcmp(pkt->BasicType, szVOID)) {
  3231. *pfResult = FALSE;
  3232. }
  3233. }
  3234. }
  3235. return WriteMore(pSrc,pCGenState, *pfResult);
  3236. }
  3237. /*
  3238. * DoesApiReturnVoid
  3239. *
  3240. */
  3241. char *DoesApiReturnVoid(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult)
  3242. {
  3243. PKNOWNTYPES pkt;
  3244. *pfResult = FALSE;
  3245. ResetLexer();
  3246. LexMacroArgs(pCGenState->ApiTypes->FuncRet);
  3247. ConsumeConstVolatileOpt();
  3248. if (ParseTypes(TypeDefsList,NULL, &pkt) == FALSE) {
  3249. CurrentTokenIndex = 0;
  3250. if (ParseTypes(StructsList, NULL, &pkt) == FALSE) {
  3251. *pfResult = TRUE;
  3252. }
  3253. }
  3254. if (!*pfResult && CurrentToken()->TokenType != TK_STAR &&
  3255. !pkt->IndLevel && !strcmp(pkt->BasicType, szVOID)) {
  3256. *pfResult = TRUE;
  3257. }
  3258. return pSrc;
  3259. }
  3260. /*
  3261. * IfApiRet
  3262. *
  3263. */
  3264. char *IfApiRet(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult)
  3265. {
  3266. pSrc = DoesApiReturnVoid(pSrc, pCGenState, pfResult);
  3267. *pfResult = !*pfResult;
  3268. pSrc = WriteMore(pSrc, pCGenState, *pfResult);
  3269. return pSrc;
  3270. }
  3271. char *
  3272. IfApiCode(
  3273. char *pSrc,
  3274. PCGENSTATE pCGenState,
  3275. BOOL * pfResult
  3276. )
  3277. /*++
  3278. Routine Description:
  3279. Expands an EFunc's codeburst, if it exists. ie. @IfApiCode(foo) will
  3280. expand to the 'foo=' section of the current EFunc, if the current EFunc
  3281. has a 'foo='. Otherwise, there is no expansion.
  3282. Arguments:
  3283. pSrc - pointer to character following '@IfApiCode'
  3284. pCGenState - current code-gen state
  3285. Return Value:
  3286. pointer to character following the end of the ')'
  3287. --*/
  3288. {
  3289. char *pch;
  3290. char *pEnd;
  3291. size_t Len;
  3292. int CodeBurstIndex;
  3293. char CodeName[MAX_PATH];
  3294. char *CodeBurst;
  3295. *pfResult = FALSE;
  3296. pch = SkipSubExpression(pSrc, NULL);
  3297. if (pSrc == pch) {
  3298. return pSrc;
  3299. }
  3300. pEnd = pch;
  3301. pch = pSrc+1;
  3302. if (IsSeparator(*pch)) {
  3303. return pSrc;
  3304. }
  3305. pSrc = pch;
  3306. while (!IsSeparator(*pch)) {
  3307. pch++;
  3308. }
  3309. Len = pch - pSrc;
  3310. // Copy name to a buffer and null-terminate
  3311. memcpy(CodeName, pSrc, Len);
  3312. CodeName[Len] = '\0';
  3313. CodeBurstIndex = GetExistingCodeBurstIndex(CodeName);
  3314. if (CodeBurstIndex == -1) {
  3315. ExitErrMsg(FALSE, "CodeBurst '%s' unknown.\n", CodeName);
  3316. }
  3317. if (pCGenState->ExTemplate) {
  3318. CodeBurst = pCGenState->TempleEx->CodeBurst[CodeBurstIndex];
  3319. if (CodeBurst) {
  3320. //
  3321. // There is an [Efunc] with a non-empty codeburst for this API.
  3322. // Generate its codeburst.
  3323. //
  3324. *pfResult = TRUE;
  3325. CGenerate(CodeBurst, pCGenState);
  3326. }
  3327. }
  3328. return pEnd;
  3329. }
  3330. /*
  3331. * CheckFastCallArgs
  3332. *
  3333. */
  3334. BOOLEAN
  3335. FastCallArgs(
  3336. PLIST_ENTRY ArgsListHead,
  3337. int ArgLimit,
  3338. BOOL fCheckTypes,
  3339. BOOL fCheckFirstArgType
  3340. )
  3341. {
  3342. PARGSLIST pArgsList;
  3343. PTEMPLES pTypeTemple;
  3344. PKNOWNTYPES pktTemple;
  3345. int NumArgs, ArgSize;
  3346. PLIST_ENTRY Next, NextTemple;
  3347. if (IsListEmpty(ArgsListHead)) {
  3348. return FALSE;
  3349. }
  3350. Next = ArgsListHead->Flink;
  3351. // check for void arg list, or vargs as first arg
  3352. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  3353. if (!pArgsList->Name) {
  3354. return strcmp(pArgsList->Type, szVARGS) ? TRUE : FALSE;
  3355. }
  3356. NumArgs = 0;
  3357. while (Next != ArgsListHead) {
  3358. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  3359. //
  3360. // Cannot have more than 4 args
  3361. //
  3362. if (++NumArgs > ArgLimit) {
  3363. return FALSE;
  3364. }
  3365. //
  3366. // arg size must be dword or less
  3367. //
  3368. ArgSize = (pArgsList->ArgSize + 3) & ~3;
  3369. if (ArgSize < 0 || ArgSize > 4) {
  3370. return FALSE;
  3371. }
  3372. //
  3373. // vargs of any indlevel aren't allowed
  3374. //
  3375. if (!strcmp(pArgsList->pKnownTypes->BaseName, szVARGS)) {
  3376. return FALSE;
  3377. }
  3378. //
  3379. // floats of Zero IndLevel aren't allowed
  3380. //
  3381. if (pArgsList->IndLevel == 0 &&
  3382. !strcmp(pArgsList->pKnownTypes->BaseName, szFLOAT))
  3383. {
  3384. return FALSE;
  3385. }
  3386. //
  3387. // type templates are not allowed except for the first arg in methods
  3388. //
  3389. if ((fCheckTypes) &&
  3390. ((NumArgs != 1) ||
  3391. ((NumArgs == 1) && fCheckFirstArgType))) {
  3392. NextTemple = TypeTempleList.Flink;
  3393. while (NextTemple != &TypeTempleList) {
  3394. pTypeTemple = CONTAINING_RECORD(NextTemple, TEMPLES, TempleEntry);
  3395. //
  3396. // get the Known types info for each type template.
  3397. //
  3398. pktTemple = pTypeTemple->pktType;
  3399. if (!pktTemple) {
  3400. //
  3401. // Don't have the Known types info yet, fetch it
  3402. // and save it in the TypeTemplate
  3403. //
  3404. pktTemple = GetNameFromTypesList(TypeDefsList,
  3405. pTypeTemple->Name
  3406. );
  3407. if (!pktTemple) {
  3408. pktTemple = GetNameFromTypesList(StructsList,
  3409. pTypeTemple->Name
  3410. );
  3411. }
  3412. pTypeTemple->pktType = pktTemple;
  3413. }
  3414. if (!pktTemple) {
  3415. ExitErrMsg(FALSE,
  3416. "Temple: Type not found %s\n",
  3417. pTypeTemple->Name
  3418. );
  3419. }
  3420. //
  3421. // See if arg matches this type template
  3422. //
  3423. if (IsSameType(pArgsList->pKnownTypes,
  3424. pArgsList->IndLevel,
  3425. TK_NONE,
  3426. pTypeTemple->Name,
  3427. pTypeTemple->IndLevel + pktTemple->IndLevel,
  3428. TK_NONE,
  3429. TRUE
  3430. ))
  3431. {
  3432. return FALSE;
  3433. }
  3434. NextTemple = NextTemple->Flink;
  3435. }
  3436. }
  3437. Next= Next->Flink;
  3438. }
  3439. return TRUE;
  3440. }
  3441. BOOLEAN
  3442. IsFastCall(
  3443. PCGENSTATE pCGenState
  3444. )
  3445. {
  3446. if (!pCGenState->ExportsDbg) { // can this occur ?
  3447. return FALSE;
  3448. }
  3449. //
  3450. // If first time, determine if Api can be a fastcall.
  3451. // tri state flag, where:
  3452. // -1 == Cannot be a fastcall
  3453. // 0 == undetermined
  3454. // 1 == Can be a fastcall
  3455. //
  3456. if (!pCGenState->ExportsDbg->FastCall) {
  3457. int Size;
  3458. pCGenState->ExportsDbg->FastCall = -1; // assume not a fastcall
  3459. //
  3460. // Fast call criteria:
  3461. // 1. NOT have an exception template.
  3462. // 2. each param up to 4 bytes (exclude structures)
  3463. // 3. 0 to 4 params
  3464. // 4. return 0 or 1 dword.
  3465. // 5. Not be a float or a VARGS
  3466. // 6. Not have have a type template
  3467. // 7. Must not be in the EFastTemplate list
  3468. // 8. Must not have a C++ linkage
  3469. //
  3470. if (!pCGenState->ExTemplate && !pCGenState->ExportsDbg->CplusDecoration) {
  3471. Size = GetRetSize(pCGenState);
  3472. if (Size >= 0 && Size <= 4 &&
  3473. !GetTemplate(&EFastTempleList, pCGenState->ExportsDbg->ExportName) &&
  3474. FastCallArgs(&pCGenState->ExportsDbg->ArgsListHead, 4, TRUE, TRUE))
  3475. {
  3476. pCGenState->ExportsDbg->FastCall = 1;
  3477. }
  3478. }
  3479. }
  3480. return pCGenState->ExportsDbg->FastCall == 1;
  3481. }
  3482. METHODTYPE
  3483. GetX2NMethodType(
  3484. PCGENSTATE pCGenState
  3485. )
  3486. {
  3487. int RetSize;
  3488. //
  3489. // Fast X2N method criteria:
  3490. // 1. NOT have an exception template.
  3491. // 2. each param up to 4 bytes (exclude structures)
  3492. // 3. Number of parameters between 1 and MAXX2NPARAMETERS
  3493. // 4. return 0 or 1 dword.
  3494. // 5. Not be a float or a VARGS
  3495. // 6. Not have have a type template, except for this pointer
  3496. // 7. Must not be in the EFastTemplate list
  3497. // 8. Must not have a C++ linkage
  3498. //
  3499. //
  3500. // Slow X2N method criteria:
  3501. // 1. NOT have an exception template.
  3502. // 2. each param up to 4 bytes (exclude structures)
  3503. // 3. Number of parameters between 1 and MAX2NPARAMETERS
  3504. // 4. return 0 or 1 dword.
  3505. // 5. Not be a float or a VARGS
  3506. // 6. Must not be in the EFastTemplate list
  3507. // 7. Must not have a C++ linkage
  3508. //
  3509. // Fat X2N methods are neither Slow X2N methods or Fast X2N methods
  3510. if (!pCGenState->ExportsDbg) { // can this occur ?
  3511. return FALSE;
  3512. }
  3513. if (pCGenState->ExportsDbg->X2NMethodType == UNKNOWNMETHOD) {
  3514. RetSize = GetRetSize(pCGenState);
  3515. if (pCGenState->ExTemplate ||
  3516. pCGenState->ExportsDbg->CplusDecoration ||
  3517. GetTemplate(&EFastTempleList, pCGenState->ExportsDbg->ExportName) ||
  3518. (RetSize > 4) || (RetSize < 0)) {
  3519. pCGenState->ExportsDbg->X2NMethodType = FATX2NMETHOD;
  3520. }
  3521. else if (FastCallArgs(&pCGenState->ExportsDbg->ArgsListHead, MAXX2NPARAMETERS, TRUE, FALSE)) {
  3522. pCGenState->ExportsDbg->X2NMethodType = FASTX2NMETHOD;
  3523. }
  3524. else if (FastCallArgs(&pCGenState->ExportsDbg->ArgsListHead, MAXX2NPARAMETERS, FALSE, FALSE)) {
  3525. pCGenState->ExportsDbg->X2NMethodType = SLOWX2NMETHOD;
  3526. }
  3527. else {
  3528. pCGenState->ExportsDbg->X2NMethodType = FATX2NMETHOD;
  3529. }
  3530. }
  3531. return(pCGenState->ExportsDbg->X2NMethodType);
  3532. }
  3533. /*
  3534. * IfRetType
  3535. *
  3536. */
  3537. char *IfRetType(char *pSrc, PCGENSTATE pCGenState, BOOL * pfResult)
  3538. {
  3539. char *pch;
  3540. *pfResult = FALSE;
  3541. pch = GetNextToken(pSrc);
  3542. if (pch != pSrc)
  3543. {
  3544. *pfResult = ( ! strncmp(pch, pCGenState->ApiTypes->FuncRet,
  3545. strlen( pCGenState->ApiTypes->FuncRet)));
  3546. }
  3547. pSrc = GetNextToken(pch);
  3548. pch = WriteMore(pSrc ,pCGenState, *pfResult);
  3549. return(pch);
  3550. }
  3551. /*
  3552. * IfNotRetType
  3553. *
  3554. */
  3555. char *IfNotRetType(char *pSrc, PCGENSTATE pCGenState)
  3556. {
  3557. char *pch;
  3558. BOOL bMore = FALSE;
  3559. pch = GetNextToken(pSrc);
  3560. if (pch != pSrc)
  3561. {
  3562. bMore = (strncmp( pch, pCGenState->ApiTypes->FuncRet, strlen( pCGenState->ApiTypes->FuncRet ) ) != 0);
  3563. }
  3564. pSrc = GetNextToken(pch);
  3565. pch = WriteMore(pSrc ,pCGenState, bMore);
  3566. return(pch);
  3567. }
  3568. BOOL
  3569. ExpandType(
  3570. PCGENSTATE pCGenState,
  3571. PKNOWNTYPES pkt,
  3572. PLIST_ENTRY pTempleList,
  3573. int CodeBurstIndex
  3574. )
  3575. {
  3576. PARGSLIST pArgsList;
  3577. PKNOWNTYPES pktTemple;
  3578. int tplIndLevel;
  3579. PLIST_ENTRY NextTemple;
  3580. PTEMPLES pTypeTemple;
  3581. int i;
  3582. pArgsList = pCGenState->pArgsList;
  3583. i=2;
  3584. while (i--) {
  3585. NextTemple = pTempleList->Flink;
  3586. while (NextTemple != pTempleList) {
  3587. pTypeTemple = CONTAINING_RECORD(NextTemple, TEMPLES, TempleEntry);
  3588. tplIndLevel = pTypeTemple->IndLevel;
  3589. pktTemple = pTypeTemple->pktType;
  3590. if (!pktTemple) {
  3591. pktTemple = GetNameFromTypesList(TypeDefsList,
  3592. pTypeTemple->Name
  3593. );
  3594. if (!pktTemple) {
  3595. pktTemple = GetNameFromTypesList(StructsList,
  3596. pTypeTemple->Name
  3597. );
  3598. }
  3599. pTypeTemple->pktType = pktTemple;
  3600. }
  3601. if (!pktTemple) {
  3602. ExitErrMsg(FALSE,
  3603. "Temple: Type not found %s\n",
  3604. pTypeTemple->Name
  3605. );
  3606. }
  3607. tplIndLevel += pktTemple->IndLevel;
  3608. if (IsSameType(pkt,
  3609. pArgsList->IndLevel,
  3610. pArgsList->tkDirection,
  3611. pTypeTemple->Name,
  3612. tplIndLevel,
  3613. pTypeTemple->tkDirection,
  3614. i == 0
  3615. )) {
  3616. DbgPrintf("ttpl: MEMBER %s.%s Type=%s IndLevel=%d\n",
  3617. pCGenState->ApiTypes->FuncRet,
  3618. pTypeTemple->Name,
  3619. pTypeTemple->Name,
  3620. pTypeTemple->IndLevel
  3621. );
  3622. if(ExpandTemple(pTypeTemple, CodeBurstIndex, pCGenState)){
  3623. return TRUE;
  3624. }
  3625. }
  3626. NextTemple = NextTemple->Flink;
  3627. }
  3628. }
  3629. return FALSE;
  3630. }
  3631. BOOL IsInNoType(PCHAR *NoTypes, PMEMBERINFO pmi) {
  3632. SIZE_T NoTypeCount;
  3633. if (NoTypes == NULL || pmi->sName == NULL) {
  3634. return FALSE;
  3635. }
  3636. for (NoTypeCount=0; NoTypeCount<MAX_NOTYPE; ++NoTypeCount) {
  3637. if (!NoTypes[NoTypeCount]) {
  3638. return FALSE;
  3639. }
  3640. else {
  3641. if (strcmp(pmi->sName, NoTypes[NoTypeCount]) == 0) {
  3642. return TRUE;
  3643. }
  3644. }
  3645. }
  3646. return FALSE;
  3647. }
  3648. SIZE_T CountNoTypes(PCHAR *NoTypes) {
  3649. SIZE_T Count = 0;
  3650. if (NoTypes == NULL) {
  3651. return 0;
  3652. }
  3653. while(*NoTypes++ != NULL) {
  3654. Count++;
  3655. }
  3656. return Count;
  3657. }
  3658. VOID pMemberTypes( PCGENSTATE pCGenState, int CodeBurstIndex, char *MemReference, BOOL bBtoT);
  3659. void ExpandMemberType( PMEMBERINFO pmi, CGENSTATE CGenState, int CodeBurstIndex,
  3660. PKNOWNTYPES pktStruct, char* pszStructName, char *pszHostCastedStructName, PARGSLIST pArgsList, FILE* fpLog,
  3661. PARGSLIST pArgsListOld, char *pMemReference, BOOL bBtoT)
  3662. {
  3663. char *sName;
  3664. char *sNameNew;
  3665. char *sHostCastedName;
  3666. int Len, HostCastedNameLen;
  3667. PKNOWNTYPES pkt;
  3668. BOOL bAddCast = TRUE;
  3669. char Type[MAX_PATH];
  3670. PARGSLIST pArgsListTemp;
  3671. // Determine if this member should be expanded by checking for a NoType entry.
  3672. if (pmi->sName != NULL) {
  3673. if(IsInNoType(CGenState.CurrentTemple->NoTypes, pmi) ||
  3674. IsInNoType(CGenState.MemberNoType, pmi)) {
  3675. goto NextMember;
  3676. }
  3677. }
  3678. // Get the pkt for the member type
  3679. if ( pmi->pktCache )
  3680. {
  3681. pkt = pmi->pktCache;
  3682. }
  3683. else
  3684. {
  3685. ResetLexer();
  3686. LexMacroArgs(pmi->sType);
  3687. ConsumeConstVolatileOpt();
  3688. if (ParseTypes(TypeDefsList,NULL, &pkt) == FALSE)
  3689. {
  3690. CurrentTokenIndex = 0;
  3691. if ( ParseTypes( StructsList, NULL, &pkt ) == FALSE )
  3692. {
  3693. fprintf( fpLog, "%s *** WARNING *** Member %s->%s skipped - unknown type\n", CGenState.Temple->Comment,
  3694. pszStructName, pmi->sType );
  3695. goto NextMember;
  3696. }
  3697. }
  3698. pmi->pktCache = pkt;
  3699. }
  3700. if ( pktStruct == pkt )
  3701. {
  3702. //
  3703. // Rats! The structure contains a member which is a pointer
  3704. // with the same type as this structure. ie. this struct
  3705. // is self-referential. We can't expand it as the expansion
  3706. // is recursive.
  3707. //
  3708. fprintf( fpLog, "%s *** WARNING *** Member %s->%s skipped - self-referencing structure\n", CGenState.Temple->Comment,
  3709. pszStructName, pmi->sType );
  3710. goto NextMember;
  3711. }
  3712. // Build the new names.
  3713. sName = pmi->sName;
  3714. // This is a type without a name. No casting is needed.
  3715. if (pktStruct->Flags & BTI_ANONYMOUS) {
  3716. if (sName == NULL) {
  3717. sHostCastedName = CheckHeapAlloc(strlen(pszHostCastedStructName) + 1);
  3718. sNameNew = CheckHeapAlloc(strlen(pszStructName) + 1);
  3719. strcpy(sHostCastedName, pszHostCastedStructName);
  3720. strcpy(sNameNew, pszStructName);
  3721. }
  3722. else {
  3723. sHostCastedName = CheckHeapAlloc(strlen(pszHostCastedStructName) + strlen(pMemReference) + strlen(sName) + 1);
  3724. strcpy(sHostCastedName, pszHostCastedStructName);
  3725. strcat(sHostCastedName, pMemReference);
  3726. strcat(sHostCastedName, sName);
  3727. sNameNew = CheckHeapAlloc(strlen(pszStructName) + strlen(pMemReference) + strlen(sName) + 1);
  3728. strcpy(sNameNew, pszStructName);
  3729. strcat(sNameNew, pMemReference);
  3730. strcat(sNameNew, sName);
  3731. }
  3732. }
  3733. else {
  3734. pArgsListTemp = CGenState.pArgsList;
  3735. CGenState.pArgsList = pArgsListOld;
  3736. if (IsPointer(&CGenState)) {
  3737. ArgTypeInd(Type, &CGenState, TRUE);
  3738. strcat(Type, " *");
  3739. }
  3740. else {
  3741. ArgHostType(Type, &CGenState);
  3742. }
  3743. if (CGenState.pArgsList->bIsBitfield ||
  3744. (CGenState.pArgsList->IndLevel == 0 &&
  3745. CGenState.pArgsList->pKnownTypes->IndLevel == 0 &&
  3746. (strcmp(CGenState.pArgsList->pKnownTypes->BasicType, "struct") == 0 ||
  3747. strcmp(CGenState.pArgsList->pKnownTypes->BasicType, "enum") == 0 ||
  3748. strcmp(CGenState.pArgsList->pKnownTypes->BasicType, "union") == 0)
  3749. )
  3750. ) {
  3751. bAddCast = FALSE;
  3752. }
  3753. else {
  3754. bAddCast = TRUE;
  3755. }
  3756. CGenState.pArgsList = pArgsListTemp;
  3757. HostCastedNameLen = strlen(pszHostCastedStructName) + strlen(Type) + 8;
  3758. Len = strlen(pszStructName) + 1;
  3759. if (sName != NULL) {
  3760. HostCastedNameLen += strlen(pMemReference) + strlen(sName);
  3761. Len += strlen(pMemReference) + strlen(sName);
  3762. }
  3763. if (Len >= MAX_PATH || HostCastedNameLen >= MAX_PATH) {
  3764. fprintf( fpLog,
  3765. "%s *** WARNING *** Member %s->%s skipped - name is too long\n",
  3766. CGenState.Temple->Comment,
  3767. pszStructName,
  3768. pmi->sType
  3769. );
  3770. goto NextMember;
  3771. }
  3772. sHostCastedName = CheckHeapAlloc(HostCastedNameLen);
  3773. sHostCastedName[0] = '\0';
  3774. if (bAddCast) {
  3775. strcpy(sHostCastedName, "((");
  3776. strcat(sHostCastedName, Type);
  3777. strcat(sHostCastedName, ")(");
  3778. strcat(sHostCastedName, pszHostCastedStructName);
  3779. strcat(sHostCastedName, "))");
  3780. }
  3781. else {
  3782. strcat(sHostCastedName, pszHostCastedStructName);
  3783. }
  3784. if(sName != NULL) {
  3785. strcat(sHostCastedName, pMemReference);
  3786. strcat(sHostCastedName, sName);
  3787. }
  3788. sNameNew = CheckHeapAlloc(Len);
  3789. strcpy(sNameNew, pszStructName);
  3790. if(sName != NULL) {
  3791. strcat(sNameNew, pMemReference);
  3792. strcat(sNameNew, sName);
  3793. }
  3794. }
  3795. pArgsList->pKnownTypes = pkt;
  3796. pArgsList->ArgSize = pkt->Size;
  3797. pArgsList->IsPtr64 = pmi->bIsPtr64;
  3798. pArgsList->OffSet = -1; // there is no stack offset for this member
  3799. pArgsList->IndLevel = pmi->IndLevel;
  3800. // pArgsList->tkDirection is same as the original arg
  3801. pArgsList->Type = pmi->sType;
  3802. pArgsList->pStructType = NULL;
  3803. pArgsList->Mod = TK_NONE;
  3804. pArgsList->SUEOpt = TK_NONE;
  3805. pArgsList->PostMod = TK_NONE;
  3806. pArgsList->PrePostMod = TK_NONE;
  3807. pArgsList->Name = sNameNew;
  3808. pArgsList->ArgLocal = sNameNew;
  3809. pArgsList->HostCastedName = sHostCastedName;
  3810. pArgsList->fIsMember = TRUE;
  3811. pArgsList->bIsBitfield = pmi->bIsBitfield;
  3812. pArgsList->BitsRequired= pmi->BitsRequired;
  3813. pArgsList->bIsArray = pmi->bIsArray;
  3814. pArgsList->ArrayElements=pmi->ArrayElements;
  3815. pArgsList->fRequiresThunk = ((pkt->Flags & BTI_CONTAINSFUNCPTR) != 0);
  3816. if (sName != NULL) {
  3817. CGenState.MemberNoType = NULL;
  3818. ExpandType(&CGenState, pArgsList->pKnownTypes, &TypeTempleList, CodeBurstIndex);
  3819. }
  3820. else {
  3821. // This field is a nameless field in a structure or union.
  3822. // Example:
  3823. // struct foobar {
  3824. // int x;
  3825. // };
  3826. // struct foobar2 {
  3827. // struct foobar;
  3828. // int y;
  3829. // };
  3830. // foobar2 will import all the fields of foobar.
  3831. //
  3832. // When walking down the structure, we want to continue expanding foobar when we reach the nameless field.
  3833. SIZE_T NumNoTypes1, NumNoTypes2;
  3834. PCHAR *NewNoTypes;
  3835. NumNoTypes1 = CountNoTypes(CGenState.MemberNoType);
  3836. NumNoTypes2 = CountNoTypes(CGenState.CurrentTemple->NoTypes);
  3837. if (NumNoTypes1 + NumNoTypes2 + 1 > MAX_NOTYPE) {
  3838. ExitErrMsg(FALSE, "ExpandMemberType: too many notypes.\n");
  3839. }
  3840. NewNoTypes = CheckHeapAlloc((NumNoTypes1 + NumNoTypes2 + 1)*sizeof(PCHAR));
  3841. memcpy(NewNoTypes, CGenState.MemberNoType, NumNoTypes1 * sizeof(PCHAR));
  3842. memcpy(NewNoTypes + NumNoTypes1, CGenState.CurrentTemple->NoTypes, NumNoTypes2 * sizeof(PCHAR));
  3843. NewNoTypes[NumNoTypes1 + NumNoTypes2] = NULL;
  3844. CGenState.MemberNoType = NewNoTypes;
  3845. pMemberTypes( &CGenState, CodeBurstIndex, pMemReference, bBtoT);
  3846. GenHeapFree(NewNoTypes);
  3847. }
  3848. GenHeapFree(sNameNew);
  3849. GenHeapFree(sHostCastedName);
  3850. NextMember:;
  3851. }
  3852. void ExpandMemberTypesBackwards( PMEMBERINFO pmi, CGENSTATE CGenState, int CodeBurstIndex,
  3853. PKNOWNTYPES pktStruct, char* pszStructName, char *pszHostCastedStructName, PARGSLIST pArgsList, FILE* fpLog,
  3854. PARGSLIST pArgsListOld, char *pMemReference, BOOL bBtoT)
  3855. {
  3856. if ( pmi->pmeminfoNext != NULL )
  3857. {
  3858. ExpandMemberTypesBackwards( pmi->pmeminfoNext, CGenState, CodeBurstIndex, pktStruct,
  3859. pszStructName, pszHostCastedStructName, pArgsList, fpLog,
  3860. pArgsListOld, pMemReference, bBtoT);
  3861. }
  3862. ExpandMemberType( pmi, CGenState, CodeBurstIndex, pktStruct,
  3863. pszStructName, pszHostCastedStructName, pArgsList, fpLog,
  3864. pArgsListOld, pMemReference, bBtoT);
  3865. }
  3866. VOID pMemberTypes( PCGENSTATE pCGenState, int CodeBurstIndex, char *MemReference, BOOL bBtoT)
  3867. {
  3868. PCGENERATE pCGen;
  3869. CGENSTATE CGenState;
  3870. PKNOWNTYPES pkt;
  3871. ARGSLIST ArgsListOld;
  3872. PMEMBERINFO pmi;
  3873. pCGen = CheckHeapAlloc(sizeof(CGENERATE)+strlen(pCGenState->CGen->TempleName)+1);
  3874. InitializeListHead(&pCGen->CGenerateEntry);
  3875. pCGen->fp = pCGenState->CGen->fp;
  3876. pCGen->FileNameC = pCGenState->CGen->FileNameC;
  3877. pCGen->FileBaseNameC = pCGenState->CGen->FileBaseNameC;
  3878. pCGen->fpCpp = pCGenState->CGen->fpCpp;
  3879. pCGen->FileNameCpp = pCGenState->CGen->FileNameCpp;
  3880. pCGen->FileBaseNameCpp = pCGenState->CGen->FileBaseNameCpp;
  3881. strcpy(pCGen->TempleName, pCGenState->CGen->TempleName);
  3882. CGenState = *pCGenState;
  3883. CGenState.CGen = pCGen;
  3884. pkt = pCGenState->pArgsList->pKnownTypes;
  3885. while(pkt->pTypedefBase != NULL) {
  3886. pkt = pkt->pTypedefBase;
  3887. }
  3888. pCGenState->pArgsList->pStructType = pkt;
  3889. // Save the old ARGSLIST away
  3890. ArgsListOld = *(pCGenState->pArgsList);
  3891. // get a ptr to the member list for the struct
  3892. pmi = pkt->pmeminfo;
  3893. if ( !pmi )
  3894. {
  3895. ExitErrMsg(FALSE, "Type '%s' is not a struct", pCGenState->pArgsList->Type);
  3896. }
  3897. if(strcmp(pkt->BasicType, "union") == 0) {
  3898. PMEMBERINFO pmiTemp;
  3899. // check if any of the members of this union are in the notype list.
  3900. for (pmiTemp = pkt->pmeminfo; pmiTemp != NULL; pmiTemp = pmiTemp->pmeminfoNext) {
  3901. if (IsInNoType(pCGenState->MemberNoType, pmiTemp) ||
  3902. IsInNoType(pCGenState->CurrentTemple->NoTypes, pmiTemp)) {
  3903. //A member of the union is in the notype list, skip union.
  3904. goto done;
  3905. }
  3906. }
  3907. }
  3908. // loop over each member variable within the type
  3909. if ( bBtoT )
  3910. {
  3911. do
  3912. {
  3913. ExpandMemberType( pmi, CGenState, CodeBurstIndex, ArgsListOld.pKnownTypes, ArgsListOld.Name,
  3914. ArgsListOld.HostCastedName, pCGenState->pArgsList, pCGenState->CGen->fp,
  3915. &ArgsListOld, MemReference, bBtoT);
  3916. pmi = pmi->pmeminfoNext;
  3917. }
  3918. while ( pmi != NULL );
  3919. }
  3920. else
  3921. {
  3922. ExpandMemberTypesBackwards( pmi, CGenState, CodeBurstIndex, ArgsListOld.pKnownTypes, ArgsListOld.Name,
  3923. ArgsListOld.HostCastedName, pCGenState->pArgsList, pCGenState->CGen->fp,
  3924. &ArgsListOld, MemReference, bBtoT);
  3925. }
  3926. done:
  3927. // Restore the old ARGSLIST
  3928. *pCGenState->pArgsList = ArgsListOld;
  3929. GenHeapFree(pCGen);
  3930. }
  3931. char* MemberTypes( char *pSrc, PCGENSTATE pCGenState, BOOL bBtoT)
  3932. /*++
  3933. Routine Description:
  3934. Expands [Type] templates for the return value of an API call.
  3935. Arguments:
  3936. pSrc - pointer to character following '@RetType'
  3937. pCGenState - current code-gen state
  3938. Return Value:
  3939. pointer to character following the end of the ')'
  3940. --*/
  3941. {
  3942. char *pEnd;
  3943. char *pch;
  3944. char BurstName[MAX_PATH];
  3945. int CodeBurstIndex;
  3946. PMACROARGSLIST pMArgsList = NULL;
  3947. SIZE_T BytesReturned;
  3948. char MemReference[MAX_PATH];
  3949. pch = SkipSubExpression(pSrc, NULL);
  3950. if (pSrc == pch) {
  3951. return pSrc;
  3952. }
  3953. pEnd = pch;
  3954. ParseMacroArgs(pSrc, pEnd - pSrc, &pMArgsList);
  3955. if (pMArgsList->NumArgs < 1 || pMArgsList->NumArgs > 2) {
  3956. ExitErrMsg(FALSE, "MemberTypes: 1 or 2 arguments are required.\n");
  3957. }
  3958. CGenerateEx(pMArgsList->ArgText[0], pCGenState, BurstName, MAX_PATH, &BytesReturned);
  3959. CodeBurstIndex = GetExistingCodeBurstIndex(BurstName);
  3960. if (CodeBurstIndex == -1) {
  3961. ExitErrMsg(FALSE, "CodeBurst '%s' unknown.\n", BurstName);
  3962. }
  3963. //handle optional member reference symbol
  3964. if (pMArgsList->NumArgs == 2) {
  3965. CGenerateEx(pMArgsList->ArgText[1], pCGenState, MemReference, MAX_PATH, &BytesReturned);
  3966. }
  3967. else {
  3968. strcpy(MemReference, "->");
  3969. }
  3970. pMemberTypes(pCGenState, CodeBurstIndex, MemReference, bBtoT);
  3971. FreeMacroArgsList(pMArgsList);
  3972. return pEnd;
  3973. }
  3974. char* ForceTypeExpand( char *pSrc, PCGENSTATE pCGenState)
  3975. {
  3976. char *pEnd;
  3977. char *pch;
  3978. PCGENERATE pCGen;
  3979. CGENSTATE CGenState;
  3980. char BurstName[MAX_PATH];
  3981. char ArgName[MAX_PATH];
  3982. char ArgHostName[MAX_PATH];
  3983. char TypeName[MAX_PATH];
  3984. char Direction[MAX_PATH];
  3985. int CodeBurstIndex;
  3986. PARGSLIST pArgsList;
  3987. ARGSLIST ArgsListOld;
  3988. ARGSLIST ArgsListNew;
  3989. TOKENTYPE tkDirection;
  3990. PMACROARGSLIST pMArgsList = NULL;
  3991. SIZE_T BytesReturned;
  3992. BOOL bHasArgsList=FALSE;
  3993. pch = SkipSubExpression(pSrc, NULL);
  3994. if (pSrc == pch) {
  3995. return pSrc;
  3996. }
  3997. pEnd = pch;
  3998. ParseMacroArgs(pSrc, pEnd - pSrc, &pMArgsList);
  3999. if (pMArgsList->NumArgs != 5) {
  4000. ExitErrMsg(FALSE, "ForceTypeExpand: 5 arguments are required.\n");
  4001. }
  4002. CGenerateEx(pMArgsList->ArgText[0], pCGenState, BurstName, MAX_PATH, &BytesReturned);
  4003. CodeBurstIndex = GetExistingCodeBurstIndex(BurstName);
  4004. if (CodeBurstIndex == -1) {
  4005. ExitErrMsg(FALSE, "CodeBurst '%s' unknown.\n", BurstName);
  4006. }
  4007. pCGen = GenHeapAlloc(sizeof(CGENERATE)+strlen(pCGenState->CGen->TempleName)+1);
  4008. if (!pCGen) {
  4009. ExitErrMsg(TRUE, "mt: %s\n", pSrc);
  4010. }
  4011. CGenerateEx(pMArgsList->ArgText[1], pCGenState, ArgName, MAX_PATH, &BytesReturned);
  4012. CGenerateEx(pMArgsList->ArgText[2], pCGenState, ArgHostName, MAX_PATH, &BytesReturned);
  4013. CGenerateEx(pMArgsList->ArgText[3], pCGenState, TypeName, MAX_PATH, &BytesReturned);
  4014. CGenerateEx(pMArgsList->ArgText[4], pCGenState, Direction, MAX_PATH, &BytesReturned);
  4015. // Parse the direction
  4016. if(strcmp(Direction, "IN OUT") == 0) {
  4017. tkDirection = TK_INOUT;
  4018. }
  4019. else if (strcmp(Direction, "IN") == 0) {
  4020. tkDirection = TK_IN;
  4021. }
  4022. else if (strcmp(Direction, "OUT") == 0) {
  4023. tkDirection = TK_OUT;
  4024. }
  4025. else if (strcmp(Direction, "none") == 0) {
  4026. tkDirection = TK_NONE;
  4027. }
  4028. else {
  4029. ExitErrMsg(FALSE, "FORCETYPE: Unknown direction %s\n", Direction);
  4030. return NULL;
  4031. }
  4032. InitializeListHead(&pCGen->CGenerateEntry);
  4033. pCGen->fp = pCGenState->CGen->fp;
  4034. pCGen->FileNameC = pCGenState->CGen->FileNameC;
  4035. pCGen->FileBaseNameC = pCGenState->CGen->FileBaseNameC;
  4036. pCGen->fpCpp = pCGenState->CGen->fpCpp;
  4037. pCGen->FileNameCpp = pCGenState->CGen->FileNameCpp;
  4038. pCGen->FileBaseNameCpp = pCGenState->CGen->FileBaseNameCpp;
  4039. strcpy(pCGen->TempleName, pCGenState->CGen->TempleName);
  4040. CGenState = *pCGenState;
  4041. CGenState.CGen = pCGen;
  4042. // Save the old ARGSLIST away
  4043. pArgsList = pCGenState->pArgsList;
  4044. if (pArgsList == NULL) {
  4045. CGenState.pArgsList = &ArgsListNew;
  4046. pArgsList = &ArgsListOld;
  4047. *pArgsList = *(PARGSLIST)pCGenState->ExportsDbg->ArgsListHead.Flink;
  4048. }
  4049. else {
  4050. ArgsListOld = *pArgsList;
  4051. bHasArgsList = TRUE;
  4052. }
  4053. pArgsList->pKnownTypes = NULL;
  4054. pArgsList->ArgSize = 0;
  4055. pArgsList->IsPtr64 = FALSE;
  4056. pArgsList->OffSet = -1; // there is no stack offset for this member
  4057. pArgsList->IndLevel = 0;
  4058. pArgsList->tkDirection = tkDirection;
  4059. pArgsList->Type = TypeName;
  4060. pArgsList->pStructType = NULL;
  4061. pArgsList->Mod = TK_NONE;
  4062. pArgsList->SUEOpt = TK_NONE;
  4063. pArgsList->PostMod = TK_NONE;
  4064. pArgsList->PrePostMod = TK_NONE;
  4065. pArgsList->Name = ArgName;
  4066. pArgsList->ArgLocal = ArgName;
  4067. pArgsList->HostCastedName = ArgHostName;
  4068. pArgsList->fIsMember = TRUE;
  4069. pArgsList->bIsBitfield = FALSE;
  4070. pArgsList->BitsRequired= FALSE;
  4071. pArgsList->bIsArray = FALSE;
  4072. pArgsList->ArrayElements=0;
  4073. pArgsList->fRequiresThunk = FALSE;
  4074. SetArgListToTypeForArg(CGenState.pArgsList, pArgsList, TypeName);
  4075. ExpandType(&CGenState, CGenState.pArgsList->pKnownTypes, &TypeTempleList, CodeBurstIndex);
  4076. // Restore the old ARGSLIST
  4077. if (bHasArgsList) {
  4078. *pCGenState->pArgsList = ArgsListOld;
  4079. }
  4080. else {
  4081. pCGenState->pArgsList = NULL;
  4082. }
  4083. GenHeapFree(pCGen);
  4084. FreeMacroArgsList(pMArgsList);
  4085. return pEnd;
  4086. }
  4087. char *
  4088. IncludeRetType(
  4089. char *pSrc,
  4090. PCGENSTATE pCGenState
  4091. )
  4092. /*++
  4093. Routine Description:
  4094. Expands [Type] templates for the return value of an API call.
  4095. Arguments:
  4096. pSrc - pointer to character following '@RetType'
  4097. pCGenState - current code-gen state
  4098. Return Value:
  4099. pointer to character following the end of the ')'
  4100. --*/
  4101. {
  4102. char *pEnd;
  4103. char *pch;
  4104. PCGENERATE pCGen;
  4105. CGENSTATE CGenState;
  4106. PKNOWNTYPES pkt;
  4107. int i;
  4108. int tplIndLevel;
  4109. PTEMPLES pTypeTemple;
  4110. PKNOWNTYPES pktTemple;
  4111. PLIST_ENTRY NextTemple;
  4112. char BurstName[MAX_PATH];
  4113. int CodeBurstIndex;
  4114. char *CodeBurst;
  4115. PMACROARGSLIST pMArgsList = NULL;
  4116. SIZE_T BytesReturned;
  4117. pch = SkipSubExpression(pSrc, NULL);
  4118. if (pSrc == pch) {
  4119. return pSrc;
  4120. }
  4121. pEnd = pch;
  4122. ParseMacroArgs(pSrc, pEnd - pSrc, &pMArgsList);
  4123. if (pMArgsList->NumArgs != 1) {
  4124. ExitErrMsg(FALSE, "IncludeRetTypes: exactly 1 argument is required.\n");
  4125. }
  4126. CGenerateEx(pMArgsList->ArgText[0], pCGenState, BurstName, MAX_PATH, &BytesReturned);
  4127. CodeBurstIndex = GetExistingCodeBurstIndex(BurstName);
  4128. if (CodeBurstIndex == -1) {
  4129. ExitErrMsg(FALSE, "CodeBurst '%s' unknown.\n", BurstName);
  4130. }
  4131. pCGen = GenHeapAlloc(sizeof(CGENERATE)+strlen(pCGenState->CGen->TempleName)+1);
  4132. if (!pCGen) {
  4133. ExitErrMsg(TRUE, "it: %s\n", pSrc);
  4134. }
  4135. InitializeListHead(&pCGen->CGenerateEntry);
  4136. pCGen->fp = pCGenState->CGen->fp;
  4137. pCGen->FileNameC = pCGenState->CGen->FileNameC;
  4138. pCGen->FileBaseNameC = pCGenState->CGen->FileBaseNameC;
  4139. pCGen->fpCpp = pCGenState->CGen->fpCpp;
  4140. pCGen->FileNameCpp = pCGenState->CGen->FileNameCpp;
  4141. pCGen->FileBaseNameCpp = pCGenState->CGen->FileBaseNameCpp;
  4142. strcpy(pCGen->TempleName, pCGenState->CGen->TempleName);
  4143. CGenState = *pCGenState;
  4144. CGenState.CGen = pCGen;
  4145. if (pCGenState->ExTemplate) {
  4146. CodeBurst = pCGenState->TempleEx->CodeBurst[CodeBurstIndex];
  4147. if (CodeBurst) {
  4148. //
  4149. // The [EFunc] template for this API has a return-type codeburst.
  4150. // That is expanded in lieu of a [Types] template.
  4151. //
  4152. CGenerate(CodeBurst, &CGenState);
  4153. return pEnd;
  4154. }
  4155. }
  4156. pkt = pCGenState->ApiTypes->pktRet;
  4157. pkt = pCGenState->ApiTypes->pktRet;
  4158. i=2;
  4159. while (i--) {
  4160. for (NextTemple = TypeTempleList.Flink ; NextTemple != &TypeTempleList ; NextTemple = NextTemple->Flink) {
  4161. pTypeTemple = CONTAINING_RECORD(NextTemple, TEMPLES, TempleEntry);
  4162. tplIndLevel = pTypeTemple->IndLevel;
  4163. pktTemple = pTypeTemple->pktType;
  4164. if (!pktTemple) {
  4165. pktTemple = GetNameFromTypesList(TypeDefsList,
  4166. pTypeTemple->Name
  4167. );
  4168. if (!pktTemple) {
  4169. pktTemple = GetNameFromTypesList(StructsList,
  4170. pTypeTemple->Name
  4171. );
  4172. }
  4173. pTypeTemple->pktType = pktTemple;
  4174. }
  4175. if (!pktTemple) {
  4176. if (bIgnorePrototypeError) {
  4177. /*
  4178. fprintf(pCGenState->CGen->fp,
  4179. "%s Error:3 Ignoring type %s\n",
  4180. pCGenState->Temple->Comment,
  4181. pTypeTemple->Name
  4182. );
  4183. */
  4184. continue;
  4185. }
  4186. else {
  4187. ExitErrMsg(FALSE,
  4188. "Temple: Type not found %s\n",
  4189. pTypeTemple->Name
  4190. );
  4191. }
  4192. }
  4193. tplIndLevel += pktTemple->IndLevel;
  4194. if (IsSameType(pkt,
  4195. pCGenState->ApiTypes->RetIndLevel,
  4196. TK_NONE,
  4197. pTypeTemple->Name,
  4198. tplIndLevel,
  4199. TK_NONE,
  4200. i == 0
  4201. )) {
  4202. DbgPrintf("ttpl: RETURN %s.%s Type=%s IndLevel=%d\n",
  4203. CGenState.ApiTypes->FuncRet,
  4204. pTypeTemple->Name,
  4205. pTypeTemple->Name,
  4206. pTypeTemple->IndLevel
  4207. );
  4208. if (pTypeTemple->CodeBurst[CodeBurstIndex]) {
  4209. pSrc = pTypeTemple->CodeBurst[CodeBurstIndex];
  4210. while (*pSrc && !isgraph(*pSrc)) {
  4211. pSrc++;
  4212. }
  4213. if (*pSrc) {
  4214. CGenerate(pSrc, &CGenState);
  4215. }
  4216. }
  4217. i = 0;
  4218. break; // break from while loop over all templates
  4219. }
  4220. }
  4221. }
  4222. GenHeapFree(pCGen);
  4223. FreeMacroArgsList(pMArgsList);
  4224. return pEnd;
  4225. }
  4226. VOID
  4227. SetArgListToTypeForArg(
  4228. PARGSLIST pArgsList,
  4229. PARGSLIST pArgsListOld,
  4230. char * pTypeName
  4231. )
  4232. {
  4233. int IndLevel = 0;
  4234. char TypeNameCopy[MAX_PATH];
  4235. PKNOWNTYPES pkt;
  4236. char *p;
  4237. BOOL bIsTypedef = TRUE;
  4238. *pArgsList = *pArgsListOld;
  4239. p = pTypeName;
  4240. strcpy(TypeNameCopy, p);
  4241. p = TypeNameCopy;
  4242. while(*p != '\0') {
  4243. if (*p == '*') {
  4244. IndLevel++;
  4245. *p = ' ';
  4246. }
  4247. p++;
  4248. }
  4249. ResetLexer();
  4250. LexMacroArgs(TypeNameCopy);
  4251. ConsumeConstVolatileOpt();
  4252. if (ParseTypes(TypeDefsList, NULL, &pkt) == FALSE) {
  4253. CurrentTokenIndex = 0;
  4254. bIsTypedef = FALSE;
  4255. if (ParseTypes(StructsList, NULL, &pkt) == FALSE ) {
  4256. ExitErrMsg(FALSE, "SetArgListToType: %s is not a valid type\n", TypeNameCopy);
  4257. }
  4258. }
  4259. pArgsList->pKnownTypes = pkt;
  4260. pArgsList->pStructType = NULL;
  4261. //DWORD ArgSize; // size of this arg (should be unchanged)
  4262. pArgsList->IsPtr64 = (IndLevel == 0 && (pkt->Flags & BTI_PTR64));
  4263. //BOOL IsPtr64; // TRUE if this arg is __ptr64 (should be unchanged)
  4264. //int OffSet; // offset from stack for this arg(should be unchanged)
  4265. pArgsList->IndLevel = IndLevel;
  4266. //TOKENTYPE tkDirection; // TK_NONE, TK_IN, TK_OUT, TK_INOUT(should be unchanged)
  4267. //TOKENTYPE Mod; // modifier (TK_CONST/VOLATILE/NONE)(should be unchanged)
  4268. if (!bIsTypedef) {
  4269. if (strcmp(pkt->BasicType, szSTRUCT) == 0) {
  4270. pArgsList->SUEOpt = TK_STRUCT;
  4271. } else if (strcmp(pkt->BasicType, szUNION) == 0) {
  4272. pArgsList->SUEOpt = TK_UNION;
  4273. } else if (strcmp(pkt->BasicType, szENUM) == 0) {
  4274. pArgsList->SUEOpt = TK_ENUM;
  4275. } else {
  4276. pArgsList->SUEOpt = TK_NONE;
  4277. }
  4278. }
  4279. pArgsList->Type = pkt->TypeName;
  4280. //TOKENTYPE PostMod; // modifier (TK_CONST/VOLATILE/NONE)
  4281. //TOKENTYPE PrePostMod; // modifier (TK_CONST/VOLATILE/NONE)
  4282. //char *Name; // argument name (may be a nonameX)
  4283. //char *ArgLocal; // name of local var containing copy of arg
  4284. //char *HostCastedName; // Contains full name of struct member with
  4285. // host casts or NULL
  4286. pArgsList->fRequiresThunk = pkt->Flags & BTI_CONTAINSFUNCPTR;
  4287. pArgsList->fNoType = FALSE; // TRUE if types templates should *not*
  4288. // be expanded for this param.
  4289. //BOOL fIsMember; // This arg is actually a member of an array
  4290. //BOOL bIsBitfield; // Determines if this is a bitfield
  4291. //int BitsRequired; // Number of bits required for bitfield
  4292. //BOOL bIsArray; // This member is an array
  4293. //int ArrayElements; // Number of elements in the array
  4294. }
  4295. BOOL
  4296. ExpandTypesForApi(
  4297. PLIST_ENTRY ArgsListHead,
  4298. PCGENSTATE CGenState,
  4299. PLIST_ENTRY pTypesList,
  4300. int CodeBurstIndex,
  4301. BOOL bExpandAll,
  4302. BOOL bRtoL
  4303. )
  4304. {
  4305. PKNOWNTYPES pktArgs;
  4306. PLIST_ENTRY NextArg;
  4307. BOOL fKeepGoing = TRUE;
  4308. //
  4309. // For each argument process a type template if any.
  4310. //
  4311. if ( bRtoL )
  4312. {
  4313. NextArg = &CGenState->ExportsDbg->ArgsListHead;
  4314. NextArg = NextArg->Blink;
  4315. }
  4316. else
  4317. {
  4318. NextArg = ArgsListHead;
  4319. }
  4320. do
  4321. {
  4322. CGenState->pArgsList = CONTAINING_RECORD(NextArg,ARGSLIST,ArgumentsEntry);
  4323. if (CGenState->pArgsList->fNoType) {
  4324. //
  4325. // This arg is listed in this API's [EFunc] NoTypes list.
  4326. // Do not expand [Types] templates for it.
  4327. //
  4328. goto NextArg;
  4329. }
  4330. ResetLexer();
  4331. LexMacroArgs(CGenState->pArgsList->Type);
  4332. ConsumeConstVolatileOpt();
  4333. // Get KnownTypes info for Argument
  4334. if (ParseTypes(TypeDefsList, NULL, &pktArgs) == FALSE) {
  4335. CurrentTokenIndex = 0;
  4336. if (ParseTypes(StructsList, NULL, &pktArgs) == FALSE ) {
  4337. ErrMsg(
  4338. "Args: Type not found %s %s\n",
  4339. CGenState->pArgsList->Type,
  4340. CGenState->ApiTypes->TypeName
  4341. );
  4342. return fKeepGoing;
  4343. }
  4344. }
  4345. fKeepGoing = !ExpandType(CGenState, CGenState->pArgsList->pKnownTypes,
  4346. pTypesList, CodeBurstIndex);
  4347. fKeepGoing = fKeepGoing | bExpandAll;
  4348. NextArg:
  4349. if ( bRtoL )
  4350. {
  4351. if ( NextArg == ArgsListHead )
  4352. {
  4353. break;
  4354. }
  4355. NextArg = NextArg->Blink;
  4356. }
  4357. else
  4358. {
  4359. NextArg = NextArg->Flink;
  4360. if ( NextArg == &CGenState->ExportsDbg->ArgsListHead )
  4361. {
  4362. break;
  4363. }
  4364. }
  4365. } while (fKeepGoing);
  4366. return fKeepGoing;
  4367. }
  4368. /*
  4369. * IncludeTypes
  4370. *
  4371. */
  4372. char *IncludeTypes(char *pSrc, PCGENSTATE pCGenState, BOOL bRtoL)
  4373. {
  4374. char *pEnd;
  4375. char *pch;
  4376. PCGENERATE pCGen;
  4377. CGENSTATE CGenState;
  4378. PARGSLIST pArgsList;
  4379. PLIST_ENTRY NextArg;
  4380. char BurstName[MAX_PATH];
  4381. PMACROARGSLIST pMArgsList = NULL;
  4382. SIZE_T BytesReturned;
  4383. int CodeBurstIndex;
  4384. pch = SkipSubExpression(pSrc, NULL);
  4385. if (pSrc == pch) {
  4386. return pSrc;
  4387. }
  4388. pEnd = pch;
  4389. //
  4390. // Functions must have an argument list (at least void)
  4391. //
  4392. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  4393. fprintf(pCGenState->CGen->fp,
  4394. "\n\t*** ERROR ***\n IncludeTypes Missing argument List: %s\n",
  4395. pCGenState->ApiTypes->TypeName
  4396. );
  4397. return pEnd;
  4398. }
  4399. //
  4400. // If void arg list, nothing to do!
  4401. //
  4402. NextArg = pCGenState->ExportsDbg->ArgsListHead.Flink;
  4403. pArgsList = CONTAINING_RECORD(NextArg, ARGSLIST, ArgumentsEntry);
  4404. if (!pArgsList->Name && strcmp(pArgsList->Type, szVARGS)) {
  4405. return pEnd;
  4406. }
  4407. ParseMacroArgs(pSrc, pEnd - pSrc, &pMArgsList);
  4408. if (pMArgsList->NumArgs < 1) {
  4409. ExitErrMsg(FALSE, "IncludeTypes: CodeBurst name required\n");
  4410. }
  4411. CGenerateEx(pMArgsList->ArgText[0], pCGenState, BurstName, MAX_PATH, &BytesReturned);
  4412. CodeBurstIndex = GetExistingCodeBurstIndex(BurstName);
  4413. if (CodeBurstIndex == -1) {
  4414. ExitErrMsg(FALSE, "CodeBurst '%s' unknown.\n", BurstName);
  4415. }
  4416. pCGen = GenHeapAlloc(sizeof(CGENERATE)+strlen(pCGenState->CGen->TempleName)+1);
  4417. if (!pCGen) {
  4418. ExitErrMsg(TRUE, "it: %s\n", pSrc);
  4419. }
  4420. InitializeListHead(&pCGen->CGenerateEntry);
  4421. pCGen->fp = pCGenState->CGen->fp;
  4422. pCGen->FileNameC = pCGenState->CGen->FileNameC;
  4423. pCGen->FileBaseNameC = pCGenState->CGen->FileBaseNameC;
  4424. pCGen->fpCpp = pCGenState->CGen->fpCpp;
  4425. pCGen->FileNameCpp = pCGenState->CGen->FileNameCpp;
  4426. pCGen->FileBaseNameCpp = pCGenState->CGen->FileBaseNameCpp;
  4427. strcpy(pCGen->TempleName, pCGenState->CGen->TempleName);
  4428. CGenState = *pCGenState;
  4429. CGenState.CGen = pCGen;
  4430. if (pMArgsList->NumArgs >= 2) {
  4431. char ArgName[MAX_PATH];
  4432. char TypeName[MAX_PATH];
  4433. char CastedArgName[MAX_PATH];
  4434. size_t ArgNameLen;
  4435. size_t ArgTypeLen;
  4436. char *p;
  4437. BOOL bHasType = FALSE;
  4438. //extract arg name to expand types for
  4439. CGenerateEx(pMArgsList->ArgText[1], pCGenState, ArgName, MAX_PATH, &BytesReturned);
  4440. if (BytesReturned == 0) {
  4441. ExitErrMsg(FALSE, "IncludeTypes: Empty arg name is not allowed.\n");
  4442. }
  4443. ArgNameLen = BytesReturned - 1;
  4444. if (pMArgsList->NumArgs == 3) {
  4445. //extract the type name
  4446. CGenerateEx(pMArgsList->ArgText[2], pCGenState, TypeName, MAX_PATH, &BytesReturned);
  4447. if (BytesReturned == 0) {
  4448. ExitErrMsg(FALSE, "IncludeTypes: Empty type name is not allowed.\n");
  4449. }
  4450. ArgTypeLen = BytesReturned - 1;
  4451. bHasType = TRUE;
  4452. if (ArgTypeLen + ArgNameLen + 4 >= MAX_PATH) {
  4453. ExitErrMsg(FALSE, "ArgType + ArgName is too long\n");
  4454. }
  4455. memcpy(CastedArgName, "((", 2);
  4456. p = CastedArgName + 2;
  4457. memcpy(p, TypeName, ArgTypeLen);
  4458. p += ArgTypeLen;
  4459. memcpy(p, ")", 1);
  4460. p++;
  4461. memcpy(p, ArgName, ArgNameLen);
  4462. p += ArgNameLen;
  4463. memcpy(p, ")", 2);
  4464. }
  4465. else {
  4466. ExitErrMsg(FALSE, "IncludeTypes: Too many arguments\n");
  4467. }
  4468. //Find arg in the arglist.
  4469. do {
  4470. pArgsList = CONTAINING_RECORD(NextArg, ARGSLIST, ArgumentsEntry);
  4471. if (pArgsList->Name != NULL) {
  4472. if (strcmp(pArgsList->Name, ArgName) == 0) {
  4473. //Expand this argument
  4474. if (bHasType) {
  4475. CGenState.pArgsList = GenHeapAlloc(sizeof(ARGSLIST));
  4476. if(NULL == CGenState.pArgsList)
  4477. ExitErrMsg(FALSE, "IncludeTypes: out of memory.\n");
  4478. SetArgListToTypeForArg(CGenState.pArgsList, pArgsList, TypeName);
  4479. CGenState.pArgsList->Name = CastedArgName;
  4480. }
  4481. else {
  4482. CGenState.pArgsList = pArgsList;
  4483. }
  4484. if (!ExpandType(&CGenState, CGenState.pArgsList->pKnownTypes, &FailTempleList, CodeBurstIndex))
  4485. ExpandType(&CGenState, CGenState.pArgsList->pKnownTypes, &TypeTempleList, CodeBurstIndex);
  4486. if (bHasType) {
  4487. GenHeapFree(CGenState.pArgsList);
  4488. }
  4489. GenHeapFree(pCGen);
  4490. FreeMacroArgsList(pMArgsList);
  4491. return pEnd;
  4492. }
  4493. }
  4494. NextArg = NextArg->Flink;
  4495. } while (NextArg != &CGenState.ExportsDbg->ArgsListHead);
  4496. ExitErrMsg(FALSE, "IncludeTypes: %s is not a known argument for %s\n", ArgName, pCGenState->ExportsDbg->ExportName);
  4497. }
  4498. else {
  4499. if (ExpandTypesForApi(NextArg,
  4500. &CGenState,
  4501. &FailTempleList,
  4502. CodeBurstIndex,
  4503. FALSE,
  4504. bRtoL)) {
  4505. ExpandTypesForApi(NextArg,
  4506. &CGenState,
  4507. &TypeTempleList,
  4508. CodeBurstIndex,
  4509. TRUE,
  4510. bRtoL);
  4511. }
  4512. }
  4513. GenHeapFree(pCGen);
  4514. FreeMacroArgsList(pMArgsList);
  4515. return pEnd;
  4516. }
  4517. /*
  4518. * IsSameType
  4519. *
  4520. */
  4521. PKNOWNTYPES
  4522. IsSameType(
  4523. PKNOWNTYPES pktArgs,
  4524. int IndLevel,
  4525. TOKENTYPE tkArgDirection,
  4526. char *tplTypeName,
  4527. int tplIndLevel,
  4528. TOKENTYPE tkTypeDirection,
  4529. BOOL bScanBaseTypes
  4530. )
  4531. {
  4532. if (*tplTypeName != '*' && strcmp(tplTypeName, "default") != 0 &&
  4533. IndLevel + pktArgs->IndLevel != tplIndLevel) {
  4534. //
  4535. // Not a generic '*' or 'default' types template, and levels of indirection
  4536. // don't match
  4537. //
  4538. return NULL;
  4539. }
  4540. if (!bUseDirection) {
  4541. tkArgDirection = TK_NONE;
  4542. }
  4543. if (tkTypeDirection != TK_EOS && tkArgDirection != tkTypeDirection) {
  4544. //
  4545. // Direction-sensitivity enabled, type template isn't generic to
  4546. // all directions, and IN, OUT, IN/OUT don't match
  4547. //
  4548. return NULL;
  4549. }
  4550. if (!strcmp(pktArgs->TypeName, tplTypeName)) {
  4551. //
  4552. // type names match
  4553. //
  4554. return pktArgs;
  4555. }
  4556. if (bScanBaseTypes) {
  4557. PKNOWNTYPES pkt;
  4558. if (strcmp(tplTypeName, "struct") == 0 &&
  4559. strcmp(pktArgs->BasicType, "struct") == 0) {
  4560. //
  4561. // This matches a generic 'struct' template.
  4562. //
  4563. return pktArgs;
  4564. }
  4565. if (strcmp(tplTypeName, "union") == 0 &&
  4566. strcmp(pktArgs->BasicType, "union") == 0) {
  4567. //
  4568. // This matches a generic 'union' template.
  4569. //
  4570. return pktArgs;
  4571. }
  4572. if (*tplTypeName == '*' && IndLevel+pktArgs->IndLevel) {
  4573. //
  4574. // The template is a generic pointer template, and the arg type
  4575. // is a pointer to something. Match.
  4576. //
  4577. return pktArgs;
  4578. }
  4579. if (!strcmp(pktArgs->BaseName, pktArgs->TypeName)) {
  4580. //
  4581. // Base name of the arg type matches this arg type, no
  4582. // possiblity of a match.
  4583. //
  4584. pkt = NULL;
  4585. goto try_default;
  4586. }
  4587. //
  4588. // Get the knowntype for basetype of the arg
  4589. //
  4590. if (pktArgs->pktBase) {
  4591. // the knowntype is already cached
  4592. pkt = pktArgs->pktBase;
  4593. } else {
  4594. pkt = GetNameFromTypesList(TypeDefsList, pktArgs->BaseName);
  4595. if (!pkt) {
  4596. pkt = GetNameFromTypesList(StructsList, pktArgs->BaseName);
  4597. }
  4598. if (!pkt) {
  4599. goto try_default;
  4600. }
  4601. pktArgs->pktBase = pkt;
  4602. }
  4603. IndLevel += pktArgs->IndLevel - pkt->IndLevel;
  4604. pkt = IsSameType(pkt,
  4605. IndLevel,
  4606. tkArgDirection,
  4607. tplTypeName,
  4608. tplIndLevel,
  4609. tkTypeDirection,
  4610. TRUE
  4611. );
  4612. if (NULL == pkt) {
  4613. try_default:
  4614. // The default type template matches everything
  4615. if (strcmp(tplTypeName, "default") == 0) {
  4616. //printf("Applying default template to %s\n", pktArgs->TypeName);
  4617. return pktArgs;
  4618. }
  4619. }
  4620. return pkt;
  4621. }
  4622. return NULL;
  4623. }
  4624. /*
  4625. * GetAltExportName
  4626. *
  4627. * Fetches the forward name if one exists, returns NULL if none.
  4628. *
  4629. */
  4630. char *GetAltExportName(char *Buffer, PCGENSTATE pCGenState, int Len)
  4631. {
  4632. PEXPORTSDEBUG pExportDebug;
  4633. int i;
  4634. pExportDebug = pCGenState->ExportsDbg;
  4635. if (pExportDebug->ExtForward) {
  4636. i = _snprintf(Buffer, Len, "=%s", pExportDebug->ExtForward);
  4637. }
  4638. else if (pExportDebug->IntForward) {
  4639. if (bNoFuzzyLogic && !strchr(pExportDebug->IntForward->ExportName, '@')) {
  4640. i = _snprintf(Buffer, Len, "=%s%s@%d",
  4641. szINTFORWARD,
  4642. pExportDebug->IntForward->ExportName,
  4643. GetArgSize(pExportDebug)
  4644. );
  4645. }
  4646. else {
  4647. i = _snprintf(Buffer, Len, "=%s%s",
  4648. szINTFORWARD,
  4649. pExportDebug->IntForward->ExportName
  4650. );
  4651. }
  4652. }
  4653. else if (bNoFuzzyLogic &&
  4654. !strchr(pExportDebug->ExportName, '@') &&
  4655. !strstr(pCGenState->ApiTypes->FuncMod, "cdecl"))
  4656. {
  4657. i = _snprintf(Buffer, Len, "=%s@%d",
  4658. pExportDebug->ExportName,
  4659. GetArgSize(pExportDebug)
  4660. );
  4661. }
  4662. else {
  4663. return NULL;
  4664. }
  4665. if (i < 0) {
  4666. ExitErrMsg(FALSE,
  4667. "GetAltExportName: Overflow %s\n",
  4668. pExportDebug->ExportName
  4669. );
  4670. }
  4671. return Buffer;
  4672. }
  4673. /*
  4674. * IncludeTemplate
  4675. *
  4676. */
  4677. char *IncludeTemplate(char *pSrc, PCGENSTATE pCGenState)
  4678. {
  4679. char *pEnd;
  4680. char *pch;
  4681. size_t Len;
  4682. PCGENERATE pCGen;
  4683. CGENSTATE CGenState;
  4684. pch = SkipSubExpression(pSrc, NULL);
  4685. if (pSrc == pch) {
  4686. return pSrc;
  4687. }
  4688. pEnd = pch;
  4689. pch = pSrc + 1;
  4690. if (IsSeparator(*pch)) {
  4691. return pSrc;
  4692. }
  4693. pSrc = pch;
  4694. while (!IsSeparator(*pch)) {
  4695. pch++;
  4696. }
  4697. Len = pch - pSrc;
  4698. pCGen = GenHeapAlloc(Len + 1 + sizeof(CGENERATE));
  4699. if (!pCGen) {
  4700. ExitErrMsg(TRUE, "it: %s\n", pSrc);
  4701. }
  4702. InitializeListHead(&pCGen->CGenerateEntry);
  4703. pCGen->fp = pCGenState->CGen->fp;
  4704. pCGen->fpC = pCGenState->CGen->fpC;
  4705. pCGen->FileNameC = pCGenState->CGen->FileNameC;
  4706. pCGen->FileBaseNameC = pCGenState->CGen->FileBaseNameC;
  4707. pCGen->fpCpp = pCGenState->CGen->fpCpp;
  4708. pCGen->FileNameCpp = pCGenState->CGen->FileNameCpp;
  4709. pCGen->FileBaseNameCpp = pCGenState->CGen->FileBaseNameCpp;
  4710. memcpy(pCGen->TempleName, pSrc, Len);
  4711. *(pCGen->TempleName + Len) = '\0';
  4712. memset(&CGenState, 0, sizeof(CGENSTATE));
  4713. CGenState.CGen = pCGen;
  4714. CGenState.ExportsDbg = pCGenState->ExportsDbg;
  4715. CGenState.DebugStrings = pCGenState->DebugStrings;
  4716. CGenState.ApiTypes = pCGenState->ApiTypes;
  4717. CGenState.ApiNum = pCGenState->ApiNum;
  4718. CGenState.pArgsList = pCGenState->pArgsList;
  4719. CGenState.ListCol = pCGenState->ListCol;
  4720. CGenState.MoreApis = pCGenState->MoreApis;
  4721. CGenState.CodeBurstIndex = pCGenState->CodeBurstIndex;
  4722. ProcessTemple(&CGenState);
  4723. GenHeapFree(pCGen);
  4724. return pEnd;
  4725. }
  4726. /*
  4727. * WriteMore
  4728. */
  4729. char *WriteMore(char *pSrc, PCGENSTATE pCGenState, BOOL bMore)
  4730. {
  4731. char *pch;
  4732. char *pExpression = 0;
  4733. CGENSTATE CGenState;
  4734. pch = SkipSubExpression(pSrc, bMore ? &pExpression : NULL);
  4735. if (pSrc == pch) {
  4736. return pSrc;
  4737. }
  4738. pSrc = pch;
  4739. if (!bMore || !pExpression) {
  4740. return pSrc;
  4741. }
  4742. CGenState = *pCGenState;
  4743. CGenerate(pExpression, &CGenState);
  4744. GenHeapFree(pExpression);
  4745. return pSrc;
  4746. }
  4747. /*
  4748. * WriteArgLocal
  4749. */
  4750. BOOL
  4751. WriteArgLocal(
  4752. PCGENSTATE pCGenState,
  4753. char *Buffer,
  4754. int BuffLen)
  4755. {
  4756. char *pch;
  4757. int i, Len;
  4758. if (pCGenState->pArgsList->ArgLocal) {
  4759. ErrMsg("Type Template error multiple ArgLocals\n");
  4760. return FALSE;
  4761. }
  4762. // format the local var name
  4763. Len = _snprintf(Buffer, BuffLen, "%s", pCGenState->pArgsList->Name);
  4764. if (Len <= 0) {
  4765. ErrMsg(
  4766. "WriteArgLocal buffer overflow %s\n",
  4767. pCGenState->pArgsList->Name
  4768. );
  4769. return FALSE;
  4770. }
  4771. // alloc space for the local var name, and stash it away
  4772. pCGenState->pArgsList->ArgLocal = GenHeapAlloc(Len + 1);
  4773. if (!pCGenState->pArgsList->ArgLocal) {
  4774. ErrMsg("GenHeapAlloc(ArgLocal) %s\n", pCGenState->pArgsList->Name);
  4775. return FALSE;
  4776. }
  4777. strcpy(pCGenState->pArgsList->ArgLocal, Buffer);
  4778. //
  4779. // format the declarator statement: "ArgType IndLevel *ArgName"
  4780. //
  4781. pch = Buffer;
  4782. i = strlen(pCGenState->pArgsList->Type) +
  4783. strlen(TokenString[pCGenState->pArgsList->SUEOpt]) + 1;
  4784. if (i >= BuffLen) {
  4785. ErrMsg(
  4786. "WriteArgLocal buffer overflow %s\n",
  4787. pCGenState->pArgsList->Name
  4788. );
  4789. return FALSE;
  4790. }
  4791. if (pCGenState->pArgsList->SUEOpt != TK_NONE) {
  4792. strcpy(pch, TokenString[pCGenState->pArgsList->SUEOpt]);
  4793. strcat(pch, " ");
  4794. strcat(pch, pCGenState->pArgsList->Type);
  4795. } else {
  4796. strcpy(pch, pCGenState->pArgsList->Type);
  4797. }
  4798. if (pCGenState->pArgsList->PrePostMod != TK_NONE) {
  4799. strcat(pch, " ");
  4800. strcat(pch, TokenString[pCGenState->pArgsList->PrePostMod]);
  4801. }
  4802. i = strlen(pch);
  4803. Len = BuffLen - i - 1;
  4804. pch += i;
  4805. i = pCGenState->pArgsList->IndLevel;
  4806. if (!Len || i > Len) {
  4807. ErrMsg(
  4808. "WriteArgLocal buffer overflow %s\n",
  4809. pCGenState->pArgsList->Name
  4810. );
  4811. return FALSE;
  4812. }
  4813. if (i) {
  4814. *pch++ = ' ';
  4815. while (i) {
  4816. *pch++ = '*';
  4817. i--;
  4818. }
  4819. }
  4820. *pch++ = ' ';
  4821. i = strlen(pCGenState->pArgsList->ArgLocal);
  4822. if (!Len || i > Len) {
  4823. ErrMsg(
  4824. "WriteArgLocal buffer overflow %s\n",
  4825. pCGenState->pArgsList->Name
  4826. );
  4827. return FALSE;
  4828. }
  4829. strcpy(pch, pCGenState->pArgsList->ArgLocal);
  4830. //
  4831. // Record that some kind of exception template has been used
  4832. // during generation of this argument.
  4833. //
  4834. pCGenState->pArgsList->fRequiresThunk = FALSE;
  4835. return TRUE;
  4836. }
  4837. /*
  4838. * WriteArgAddr
  4839. */
  4840. char *
  4841. WriteArgAddr(
  4842. char *pSrc,
  4843. PCGENSTATE pCGenState,
  4844. char *Buffer,
  4845. int BuffLen)
  4846. {
  4847. char *pEnd;
  4848. char *pch;
  4849. size_t Len;
  4850. pch = SkipSubExpression(pSrc, NULL);
  4851. if (pSrc == pch) {
  4852. return pSrc;
  4853. }
  4854. pEnd = pch;
  4855. Len = --pch - ++pSrc;
  4856. if (Len + 32 >= (size_t)BuffLen) {
  4857. ExitErrMsg(FALSE,
  4858. "WriteArgAddr buffer overflow %s\n",
  4859. pSrc
  4860. );
  4861. }
  4862. while (pSrc < pch) {
  4863. *Buffer++ = *pSrc++;
  4864. }
  4865. *Buffer++ = ' ';
  4866. *Buffer++ = '+';
  4867. *Buffer++ = ' ';
  4868. _itoa(pCGenState->pArgsList->OffSet, Buffer, 10);
  4869. return pEnd;
  4870. }
  4871. BOOLEAN
  4872. TempleHasNoCodeBursts(
  4873. PTEMPLES pTemple
  4874. )
  4875. /*++
  4876. Routine Description:
  4877. Determines if a template has no codebursts at all or not.
  4878. Arguments:
  4879. pTemple - template to examine
  4880. Return Value:
  4881. TRUE if template has no codebursts, FALSE if there is at least one.
  4882. --*/
  4883. {
  4884. int i;
  4885. for (i=0; i<MAX_CODEBURST; ++i) {
  4886. if (pTemple->CodeBurst[i]) {
  4887. return FALSE;
  4888. }
  4889. }
  4890. return TRUE;
  4891. }
  4892. /*
  4893. * ListApis
  4894. */
  4895. char *ListApis(char *pSrc, PCGENSTATE pCGenState, BOOL bExports)
  4896. {
  4897. char *pch;
  4898. char *pExpression;
  4899. PLIST_ENTRY Next;
  4900. CGENSTATE CGenState;
  4901. PTEMPLES pTemple;
  4902. BYTE ApiPlatform;
  4903. BOOL ExcludedApi;
  4904. pch = SkipSubExpression(pSrc, &pExpression);
  4905. if (pSrc == pch || !pExpression) {
  4906. return pch;
  4907. }
  4908. pSrc = pch;
  4909. memset(&CGenState, 0, sizeof(CGenState));
  4910. CGenState.CGen = pCGenState->CGen;
  4911. CGenState.Temple = pCGenState->Temple;
  4912. CGenState.MoreApis = TRUE;
  4913. CGenState.ListCol = pCGenState->ListCol;
  4914. CGenState.CodeBurstIndex = pCGenState->CodeBurstIndex;
  4915. Next = ExportsList.Flink;
  4916. while (Next != &ExportsList) {
  4917. CGenState.ExportsDbg = CONTAINING_RECORD(Next,
  4918. EXPORTSDEBUG,
  4919. ExportsDbgEntry
  4920. );
  4921. Next= Next->Flink;
  4922. if (Next == &ExportsList) {
  4923. CGenState.MoreApis = FALSE;
  4924. }
  4925. //
  4926. // Switch this API in or out depending on the platform info
  4927. //
  4928. ApiPlatform = CGenState.ExportsDbg->ApiPlatform;
  4929. PlatformSwitchStart(&CGenState, ApiPlatform);
  4930. CGenState.ApiTypes = GetApiTypes(CGenState.ExportsDbg);
  4931. pTemple = GetTemplate(&EFuncTempleList,
  4932. CGenState.ExportsDbg->ExportName
  4933. );
  4934. ExcludedApi = FALSE;
  4935. // skip this api if ex template, but no code
  4936. if (!bExports && pTemple && TempleHasNoCodeBursts(pTemple)) {
  4937. ExcludedApi = TRUE;
  4938. fprintf(pCGenState->CGen->fp,
  4939. "%s *** WARNING *** Excluded Api %s\n",
  4940. CGenState.Temple->Comment,
  4941. CGenState.ExportsDbg->ExportName
  4942. );
  4943. }
  4944. //
  4945. // skip this api if:
  4946. // - external forward reference
  4947. // - internal forward which does not define the function.
  4948. // (exportname != forwardname)
  4949. //
  4950. else if (!bExports &&
  4951. (CGenState.ExportsDbg->ExtForward ||
  4952. (CGenState.ExportsDbg->IntForward &&
  4953. CGenState.ExportsDbg->IntForward != CGenState.ExportsDbg)))
  4954. {
  4955. ExcludedApi = TRUE;
  4956. fprintf(pCGenState->CGen->fp,
  4957. "%s %s forwarded to %s\n",
  4958. CGenState.Temple->Comment,
  4959. CGenState.ExportsDbg->ExportName,
  4960. CGenState.ExportsDbg->ExtForward
  4961. ? CGenState.ExportsDbg->ExtForward
  4962. : CGenState.ExportsDbg->IntForward->ExportName
  4963. );
  4964. }
  4965. // skip this api if DATA and no ex template
  4966. else if (!pTemple && CGenState.ExportsDbg->Data) {
  4967. ExcludedApi = TRUE;
  4968. fprintf(pCGenState->CGen->fp,
  4969. "%s *** WARNING *** Excluded Data Export %s\n",
  4970. CGenState.Temple->Comment,
  4971. CGenState.ExportsDbg->ExportName
  4972. );
  4973. }
  4974. // skip this api if CPP export and we aren't setup for CPP exports,
  4975. else if (!pTemple && !iHandleCpp && CGenState.ExportsDbg->CplusDecoration)
  4976. {
  4977. ExcludedApi = TRUE;
  4978. fprintf(pCGenState->CGen->fp,
  4979. "%s *** WARNING *** Excluding CPP Api: %s\n",
  4980. CGenState.Temple->Comment,
  4981. CGenState.ExportsDbg->ExportName
  4982. );
  4983. }
  4984. // skip this api if members are unknown
  4985. else if (!CGenState.ApiTypes->pfuncinfo) {
  4986. ExcludedApi = TRUE;
  4987. // members unknown - skip the API
  4988. if (bIgnorePrototypeError)
  4989. {
  4990. fprintf(pCGenState->CGen->fp,
  4991. "%s Error:4 Ignoring Api %s\n",
  4992. CGenState.Temple->Comment,
  4993. CGenState.ExportsDbg->ExportName
  4994. );
  4995. }
  4996. else {
  4997. ExitErrMsg(FALSE,
  4998. "API %s has no function prototype - unable to generate code.",
  4999. CGenState.ExportsDbg->ExportName
  5000. );
  5001. }
  5002. }
  5003. // gen code for this api
  5004. else {
  5005. if (pTemple) {
  5006. CGenState.ExTemplate= TRUE;
  5007. }
  5008. else {
  5009. CGenState.ExTemplate= FALSE;
  5010. }
  5011. BuildArgsList(pTemple,
  5012. CGenState.ApiTypes->pfuncinfo,
  5013. &CGenState.ExportsDbg->ArgsListHead
  5014. );
  5015. if (GetArgSize(CGenState.ExportsDbg) < 0) {
  5016. ExcludedApi = TRUE;
  5017. // members unknown - skip the API
  5018. if (bIgnorePrototypeError)
  5019. {
  5020. fprintf(pCGenState->CGen->fp,
  5021. "%s Error:5 Ignoring Api %s\n",
  5022. CGenState.Temple->Comment,
  5023. CGenState.ExportsDbg->ExportName
  5024. );
  5025. }
  5026. else {
  5027. ExitErrMsg(FALSE,
  5028. "API %s has no function prototype - unable to generate code.",
  5029. CGenState.ExportsDbg->ExportName
  5030. );
  5031. }
  5032. }
  5033. else {
  5034. CGenerate(pExpression, &CGenState);
  5035. if (bExports) {
  5036. //
  5037. // we're generating the .DEF file. Mark some APIs
  5038. // as private so the linker doesn't warn us.
  5039. //
  5040. if (strcmp(CGenState.ExportsDbg->ExportName,
  5041. "DllGetClassObject") == 0 ||
  5042. strcmp(CGenState.ExportsDbg->ExportName,
  5043. "DllCanUnloadNow") == 0 ||
  5044. strcmp(CGenState.ExportsDbg->ExportName,
  5045. "DllRegisterServer") == 0 ||
  5046. strcmp(CGenState.ExportsDbg->ExportName,
  5047. "DllRegisterServerEx") == 0 ||
  5048. strcmp(CGenState.ExportsDbg->ExportName,
  5049. "DllInstall") == 0 ||
  5050. strcmp(CGenState.ExportsDbg->ExportName,
  5051. "DllUnregisterServer") == 0) {
  5052. fprintf(pCGenState->CGen->fp, " PRIVATE");
  5053. }
  5054. }
  5055. CGenState.ApiNum++;
  5056. }
  5057. }
  5058. if (bExports)
  5059. PlatformSwitchEnd(&CGenState, ApiPlatform);
  5060. else{
  5061. if (ExcludedApi)
  5062. PlatformSwitchEnd(&CGenState, ApiPlatform);
  5063. else
  5064. PlatformSwitchEndTable(&CGenState, ApiPlatform);
  5065. }
  5066. if (CGenState.ListCol) {
  5067. WriteListColumn(&CGenState);
  5068. }
  5069. }
  5070. GenHeapFree(pExpression);
  5071. return pSrc;
  5072. }
  5073. PKNOWNTYPES
  5074. BuildFakeTypesInfo(
  5075. PEXPORTSDEBUG pExportsDbg,
  5076. PKNOWNTYPES pKnownTypes
  5077. )
  5078. {
  5079. TYPESINFO ti;
  5080. int ArgsSize, i;
  5081. size_t Len;
  5082. PFUNCINFO funcinfo;
  5083. char *pch;
  5084. memset(&ti, 0, sizeof(TYPESINFO));
  5085. strcpy(ti.TypeName, pExportsDbg->ExportName);
  5086. if (pKnownTypes) {
  5087. strcpy(ti.BasicType, pKnownTypes->BasicType);
  5088. strcpy(ti.BaseName, pKnownTypes->BaseName);
  5089. strcpy(ti.FuncRet, pKnownTypes->FuncRet);
  5090. strcpy(ti.FuncMod, pKnownTypes->FuncMod);
  5091. pExportsDbg->UnKnownApi = -1; // incomplete fn declaration
  5092. /*
  5093. * WARNING:
  5094. * The type is added to the FakeFuncsList with args
  5095. * info from the dll symbols. The type is NOT removed
  5096. * from the FuncsList.
  5097. */
  5098. }
  5099. else {
  5100. strcpy(ti.BasicType, szFUNC);
  5101. strcpy(ti.FuncRet, szINT);
  5102. pExportsDbg->UnKnownApi = 1; // missing fn declaration
  5103. }
  5104. ArgsSize = pExportsDbg->ArgsSize;
  5105. if (!ArgsSize) {
  5106. ti.TypeKind = TypeKindFunc;
  5107. ti.dwMemberSize = sizeof(FUNCINFO) + strlen(szVOID) + 1;
  5108. ti.pfuncinfo = (PFUNCINFO)ti.Members;
  5109. pch = ti.Members + sizeof(FUNCINFO);
  5110. strcpy(pch, szVOID);
  5111. ti.pfuncinfo->sType = pch;
  5112. }
  5113. else if (ArgsSize < 0) {
  5114. ;
  5115. }
  5116. else {
  5117. ti.TypeKind = TypeKindFunc;
  5118. pch = ti.Members + sizeof(FUNCINFO);
  5119. Len = sizeof(ti.Members) - 1 - sizeof(FUNCINFO);
  5120. funcinfo = (PFUNCINFO)ti.Members;
  5121. ti.pfuncinfo = funcinfo;
  5122. while (ArgsSize && Len) {
  5123. ti.dwMemberSize+=sizeof(FUNCINFO);
  5124. i = _snprintf(pch, Len, "Fake%x", ArgsSize);
  5125. if (i < 0) {
  5126. return NULL;
  5127. }
  5128. i++;
  5129. Len -= i;
  5130. funcinfo->sName = pch;
  5131. pch += i;
  5132. ti.dwMemberSize+=i;
  5133. strcpy(pch, szINT);
  5134. funcinfo->sType = pch;
  5135. i = strlen(szINT) + 1;
  5136. pch += i;
  5137. ti.dwMemberSize+=i;
  5138. ArgsSize -= sizeof(int);
  5139. if (ArgsSize) {
  5140. PFUNCINFO funcinfoNext;
  5141. INT_PTR Realignment;
  5142. //
  5143. // Allocate space for another FUNCINFO, ensuring that
  5144. // it is DWORD-aligned.
  5145. //
  5146. Len -= sizeof(FUNCINFO);
  5147. Realignment = 4 - ((INT_PTR)pch & 3);
  5148. Len -= Realignment;
  5149. funcinfoNext = (PFUNCINFO)(pch + Realignment);
  5150. pch += sizeof(FUNCINFO)+Realignment;
  5151. ti.dwMemberSize += (DWORD)Realignment;
  5152. if ((INT_PTR)Len < 0) {
  5153. return NULL;
  5154. }
  5155. funcinfo->pfuncinfoNext = funcinfoNext;
  5156. funcinfo = funcinfoNext;
  5157. }
  5158. }
  5159. }
  5160. return AddToTypesList(&FakeFuncsList, &ti);
  5161. }
  5162. /*
  5163. * GetFuncArgNum
  5164. */
  5165. int GetFuncArgNum(PCGENSTATE pCGenState)
  5166. {
  5167. PARGSLIST pArgsList;
  5168. PKNOWNTYPES pkt;
  5169. int NumArgs;
  5170. PFUNCINFO funcinfo;
  5171. pArgsList = pCGenState->pArgsList;
  5172. if (!pArgsList) {
  5173. fprintf(pCGenState->CGen->fp,
  5174. "\n\t*** ERROR ***\n*** GetFuncArgNum Missing argument List\n\n"
  5175. );
  5176. return -1;
  5177. }
  5178. pkt = pArgsList->pKnownTypes;
  5179. while (!pkt->Members || !pkt->pfuncinfo) {
  5180. if (pkt->pktBase) {
  5181. // the knowntype is already cached
  5182. pkt = pkt->pktBase;
  5183. } else {
  5184. PKNOWNTYPES pktOrg = pkt;
  5185. pkt = GetNameFromTypesList(TypeDefsList, pkt->BaseName);
  5186. if (!pkt) {
  5187. if (pArgsList->pKnownTypes) {
  5188. fprintf(pCGenState->CGen->fp,
  5189. "\n\t*** ERROR ***\n*** GetFuncArgNum BaseType Not found:<%s:%s>\n\n",
  5190. pArgsList->pKnownTypes->TypeName,
  5191. pArgsList->pKnownTypes->BasicType
  5192. );
  5193. } else {
  5194. fprintf(pCGenState->CGen->fp,
  5195. "\n\t*** ERRR ***\n*** GetFuncArgNum BaseType Not found: no KnownTypes\n\n"
  5196. );
  5197. }
  5198. return -1;
  5199. }
  5200. pktOrg->pktBase = pkt;
  5201. }
  5202. if (!strcmp(pkt->BasicType, pkt->TypeName)) {
  5203. break;
  5204. }
  5205. }
  5206. funcinfo = pkt->pfuncinfo;
  5207. if (!pkt->Members || !funcinfo) {
  5208. fprintf(pCGenState->CGen->fp,
  5209. "/*** WARN gfan No Members:<%s:%s> ***/ ",
  5210. pArgsList->pKnownTypes->TypeName,
  5211. pkt->BasicType
  5212. );
  5213. return 0;
  5214. }
  5215. //
  5216. // "..." vargs is nonsense can't do it!
  5217. //
  5218. if (strcmp(funcinfo->sType, szVARGS) == 0) {
  5219. fprintf(pCGenState->CGen->fp,
  5220. "\n\t*** ERROR ***\n*** GetFuncArgNum variable Args:<%s:%s>\n\n",
  5221. pArgsList->pKnownTypes->TypeName,
  5222. pkt->BasicType
  5223. );
  5224. return -1;
  5225. }
  5226. //
  5227. // void arg list, Zero Args
  5228. //
  5229. if (strcmp(funcinfo->sType, szVOID) == 0) {
  5230. return 0;
  5231. }
  5232. NumArgs = 0;
  5233. do {
  5234. NumArgs++;
  5235. funcinfo = funcinfo->pfuncinfoNext;
  5236. } while(funcinfo);
  5237. return NumArgs;
  5238. }
  5239. /*
  5240. * GetFuncIndex
  5241. */
  5242. int GetFuncIndex(PCGENSTATE pCGenState, char *FuncTypeName)
  5243. {
  5244. PKNOWNTYPES pkt, pktFunc;
  5245. int Len, LenExpr, LenArgs, LenRet;
  5246. char *pch;
  5247. char Args[1024];
  5248. PFUNCINFO funcinfo;
  5249. PDEBUGSTRINGS DebugStrings;
  5250. if (!FuncTypeName || !*FuncTypeName) {
  5251. fprintf(pCGenState->CGen->fp,
  5252. "\n\t*** ERROR ***\n*** GetFuncIndex TypeName Not specified\n\n"
  5253. );
  5254. return -1;
  5255. }
  5256. pkt = GetNameFromTypesList(TypeDefsList, FuncTypeName);
  5257. if (!pkt) {
  5258. fprintf(pCGenState->CGen->fp,
  5259. "\n\t*** ERROR ***\n*** GetFuncIndex Type Not found:<%s>\n\n",
  5260. FuncTypeName
  5261. );
  5262. return -1;
  5263. }
  5264. pktFunc = pkt;
  5265. while (!pkt->Members || !pkt->pfuncinfo) {
  5266. // NOTE: we cannot look at pkt->pktBase as it may point to a struct
  5267. // knowntype instead of a typedef
  5268. pkt = GetNameFromTypesList(TypeDefsList, pkt->BaseName);
  5269. if (!pkt) {
  5270. fprintf(pCGenState->CGen->fp,
  5271. "\n\t*** ERROR ***\n*** GetFuncIndex BaseType Not found:<%s:%s>\n\n",
  5272. FuncTypeName,
  5273. pktFunc->BaseName
  5274. );
  5275. return -1;
  5276. }
  5277. if (!strcmp(pkt->BasicType, pkt->TypeName)) {
  5278. break;
  5279. }
  5280. }
  5281. LenArgs = 1;
  5282. Args[0] = '\0';
  5283. funcinfo = pkt->pfuncinfo;
  5284. if (pkt->Members && funcinfo) {
  5285. //
  5286. // "..." vargs is nonsense can't do it!
  5287. //
  5288. if (strcmp(funcinfo->sType, szVARGS) == 0) {
  5289. fprintf(pCGenState->CGen->fp,
  5290. "\n\t*** ERROR ***\n*** GetFuncIndex variable Args:<%s:%s>\n\n",
  5291. FuncTypeName,
  5292. pkt->BasicType
  5293. );
  5294. return -1;
  5295. }
  5296. //
  5297. // void arg list means no args
  5298. //
  5299. if (strcmp(funcinfo->sType, szVOID) != 0) {
  5300. pch = Args;
  5301. do {
  5302. //
  5303. // Copy in the typename
  5304. //
  5305. Len = strlen(funcinfo->sType);
  5306. LenArgs += Len;
  5307. if (LenArgs >= sizeof(Args)-3) {
  5308. break;
  5309. }
  5310. strcpy(pch, funcinfo->sType);
  5311. pch += Len;
  5312. //
  5313. // Copy in the levels of indirection
  5314. //
  5315. LenArgs += funcinfo->IndLevel;
  5316. if (LenArgs >= sizeof(Args)-3) {
  5317. break;
  5318. }
  5319. for (Len = 0; Len<funcinfo->IndLevel; ++Len) {
  5320. *pch++ = '*';
  5321. }
  5322. //
  5323. // Copy in the argument name, if present
  5324. //
  5325. if (funcinfo->sName) {
  5326. Len = strlen(funcinfo->sName) + 1;
  5327. LenArgs += Len;
  5328. if (LenArgs >= sizeof(Args)-3) {
  5329. break;
  5330. }
  5331. *pch = ' ';
  5332. strcpy(pch+1, funcinfo->sName);
  5333. pch += Len;
  5334. }
  5335. //
  5336. // Copy in the printf-style formatting for this argument
  5337. //
  5338. LenArgs += 3;
  5339. *pch++ = ' ';
  5340. *pch++ = '%';
  5341. *pch++ = 'x';
  5342. funcinfo = funcinfo->pfuncinfoNext;
  5343. if (funcinfo) {
  5344. LenArgs+=2;
  5345. *pch++ = ',';
  5346. *pch++ = ' ';
  5347. }
  5348. } while (funcinfo);
  5349. if (LenArgs >= sizeof(Args)-5) {
  5350. ExitErrMsg(FALSE,
  5351. "GetFuncIndex overflow %s.%s\n",
  5352. FuncTypeName,
  5353. pkt->Members
  5354. );
  5355. }
  5356. }
  5357. //
  5358. // Null-terminate the Args[] string.
  5359. //
  5360. Args[LenArgs-1] = '\0';
  5361. }
  5362. LenExpr = strlen(FuncTypeName) + 1;
  5363. LenRet = strlen(pkt->FuncRet) + 4;
  5364. DebugStrings = GenHeapAlloc(LenExpr + LenRet + LenArgs + sizeof(DEBUGSTRINGS));
  5365. if (!DebugStrings) {
  5366. ExitErrMsg(TRUE,
  5367. "GetFuncIndex: GenHeapAlloc(DebugStrings) %s.%s\n",
  5368. FuncTypeName,
  5369. pkt->Members
  5370. );
  5371. }
  5372. Len = 0;
  5373. DebugStrings->Name = DebugStrings->Buffer;
  5374. strcpy(DebugStrings->Name, FuncTypeName);
  5375. Len += LenExpr;
  5376. DebugStrings->ArgFormat = DebugStrings->Buffer + Len;
  5377. strcpy(DebugStrings->ArgFormat, Args);
  5378. Len += LenArgs;
  5379. DebugStrings->RetFormat = DebugStrings->Buffer + Len;
  5380. strcpy(DebugStrings->RetFormat, pkt->FuncRet);
  5381. strcat(DebugStrings->RetFormat, " %x");
  5382. Len += LenRet;
  5383. InsertTailList(&DebugStringsList, &DebugStrings->DebugStringsEntry);
  5384. return NumDebugStringsEntries++;
  5385. }
  5386. /*
  5387. * WriteDbgsStrings
  5388. *
  5389. */
  5390. void WriteDbgsStrings(char *pSrc, PCGENSTATE pCGenState)
  5391. {
  5392. DEBUGSTRINGS DebugStrings;
  5393. char BaseName[MAX_PATH];
  5394. char *c;
  5395. // copy in the DLL name and whack off the extension
  5396. strcpy(BaseName, DllBaseName);
  5397. c = strchr(BaseName, '.');
  5398. if (c) {
  5399. *c = '\0';
  5400. }
  5401. if (!pCGenState->DebugStrings) {
  5402. pCGenState->DebugStrings = &DebugStrings;
  5403. DebugStrings.Name =
  5404. DebugStrings.ArgFormat =
  5405. DebugStrings.RetFormat = "";
  5406. }
  5407. fprintf(pCGenState->CGen->fp,
  5408. "\"%s!%s\",\"%s\",\"%s\"",
  5409. BaseName,
  5410. pCGenState->DebugStrings->Name,
  5411. pCGenState->DebugStrings->ArgFormat,
  5412. pCGenState->DebugStrings->RetFormat
  5413. );
  5414. }
  5415. /*
  5416. * ListDbgs
  5417. */
  5418. char *ListDbgs(char *pSrc, PCGENSTATE pCGenState)
  5419. {
  5420. char *pch;
  5421. char *pExpression;
  5422. PLIST_ENTRY Next;
  5423. CGENSTATE CGenState;
  5424. pch = SkipSubExpression(pSrc, &pExpression);
  5425. if (pSrc == pch || !pExpression) {
  5426. return pch;
  5427. }
  5428. pSrc = pch;
  5429. memset(&CGenState, 0, sizeof(CGenState));
  5430. CGenState.CGen = pCGenState->CGen;
  5431. CGenState.Temple = pCGenState->Temple;
  5432. CGenState.ListCol = pCGenState->ListCol;
  5433. if (!IsListEmpty(&DebugStringsList)) {
  5434. Next = DebugStringsList.Flink;
  5435. while (Next != &DebugStringsList) {
  5436. CGenState.DebugStrings = CONTAINING_RECORD(Next,
  5437. DEBUGSTRINGS,
  5438. DebugStringsEntry
  5439. );
  5440. Next= Next->Flink;
  5441. CGenState.MoreApis = (Next != &DebugStringsList) ? TRUE : FALSE;
  5442. CGenerate(pExpression, &CGenState);
  5443. if (CGenState.ListCol) {
  5444. WriteListColumn(&CGenState);
  5445. }
  5446. }
  5447. }
  5448. else {
  5449. CGenState.MoreApis = FALSE;
  5450. CGenerate(pExpression, &CGenState);
  5451. if (CGenState.ListCol) {
  5452. WriteListColumn(&CGenState);
  5453. }
  5454. }
  5455. GenHeapFree(pExpression);
  5456. return pSrc;
  5457. }
  5458. /*
  5459. * ListArgs
  5460. */
  5461. char *ListArgs(char *pSrc, PCGENSTATE pCGenState, BOOL Always)
  5462. {
  5463. PARGSLIST pArgsList;
  5464. PLIST_ENTRY Next;
  5465. char *pch;
  5466. char *pExpression;
  5467. CGENSTATE CGenState;
  5468. if (IsListEmpty(&pCGenState->ExportsDbg->ArgsListHead)) {
  5469. fprintf(pCGenState->CGen->fp,
  5470. "\n\t*** ERROR ***\n*** ListArgs Missing argument List: %s\n\n",
  5471. pCGenState->ApiTypes->TypeName
  5472. );
  5473. return SkipSubExpression(pSrc, NULL);
  5474. }
  5475. Next = pCGenState->ExportsDbg->ArgsListHead.Flink;
  5476. // check for void arg list
  5477. if (!Always) {
  5478. pArgsList = CONTAINING_RECORD(Next, ARGSLIST, ArgumentsEntry);
  5479. if (!pArgsList->Name && strcmp(pArgsList->Type, szVARGS)) {
  5480. return SkipSubExpression(pSrc, NULL);
  5481. }
  5482. }
  5483. CGenState = *pCGenState;
  5484. pch = SkipSubExpression(pSrc, &pExpression);
  5485. if (pSrc == pch || !pExpression) {
  5486. return pch;
  5487. }
  5488. pSrc = pch;
  5489. do {
  5490. CGenState.pArgsList = CONTAINING_RECORD(Next,ARGSLIST, ArgumentsEntry);
  5491. CGenerate(pExpression, &CGenState);
  5492. if (!g_fLessTrailingWhitespace || Next->Flink != &CGenState.ExportsDbg->ArgsListHead)
  5493. if (CGenState.ListCol) {
  5494. WriteListColumn(&CGenState);
  5495. }
  5496. Next= Next->Flink;
  5497. } while (Next != &CGenState.ExportsDbg->ArgsListHead);
  5498. GenHeapFree(pExpression);
  5499. return pSrc;
  5500. }
  5501. /*
  5502. * WriteListColumn
  5503. */
  5504. void WriteListColumn(PCGENSTATE pCGenState)
  5505. {
  5506. int Len;
  5507. FILE *fp = pCGenState->CGen->fp;
  5508. OutputColumn = pCGenState->ListCol;
  5509. Len = OutputColumn - 1;
  5510. if (fputc('\n', fp) != '\n') {
  5511. ExitErrMsg(TRUE, "fputc %s\n", pCGenState->CGen->FileNameC);
  5512. return;
  5513. }
  5514. while (Len--) {
  5515. if (fputc(' ', fp) != ' ') {
  5516. ExitErrMsg(TRUE, "fputc %s\n", pCGenState->CGen->FileNameC);
  5517. }
  5518. }
  5519. }
  5520. /*
  5521. * SkipSubExpression
  5522. *
  5523. */
  5524. char *SkipSubExpression(char *pSrc, char **pSubExpression)
  5525. {
  5526. char *pOrg = pSrc;
  5527. char *pSave;
  5528. int Len = 0;
  5529. int ParenLevel;
  5530. if ((*pSrc != '(') && (*pSrc != ',')) {
  5531. return pOrg;
  5532. }
  5533. pSrc++;
  5534. pSave = pSrc;
  5535. ParenLevel = 1;
  5536. Len = 0;
  5537. while (*pSrc) {
  5538. if (*pSrc == '(') {
  5539. ParenLevel++;
  5540. }
  5541. else if (*pSrc == ')') {
  5542. ParenLevel--;
  5543. }
  5544. pSrc++;
  5545. if (!ParenLevel) {
  5546. break;
  5547. }
  5548. Len++;
  5549. }
  5550. if (pSubExpression) {
  5551. if (Len) {
  5552. *pSubExpression = GenHeapAlloc(Len + 1);
  5553. if (!*pSubExpression) {
  5554. ExitErrMsg(TRUE, "GenHeapAlloc(SubExpression) %s\n", pOrg);
  5555. }
  5556. if (Len) {
  5557. memcpy(*pSubExpression, pSave, Len);
  5558. }
  5559. *(*pSubExpression + Len) = '\0';
  5560. }
  5561. else {
  5562. *pSubExpression = NULL;
  5563. }
  5564. }
  5565. return pSrc;
  5566. }
  5567. /*
  5568. * GetTemplate
  5569. */
  5570. PTEMPLES GetTemplate(PLIST_ENTRY pHeadList, char *TempleName)
  5571. {
  5572. PTEMPLES ptpl;
  5573. PLIST_ENTRY Next;
  5574. Next = pHeadList->Flink;
  5575. while (Next != pHeadList) {
  5576. ptpl = CONTAINING_RECORD(Next, TEMPLES, TempleEntry);
  5577. if (!strcmp(ptpl->Name, TempleName)) {
  5578. return ptpl;
  5579. }
  5580. Next= Next->Flink;
  5581. }
  5582. return NULL;
  5583. }
  5584. void
  5585. UseLogMacros(char *LogName)
  5586. {
  5587. DWORD Len;
  5588. char FullLogName[MAX_PATH+1];
  5589. char *LogBaseName;
  5590. Len = GetFullPathName(LogName,
  5591. sizeof(FullLogName) - 1,
  5592. FullLogName,
  5593. &LogBaseName
  5594. );
  5595. if (Len == 0 || Len >= sizeof(FullLogName) - 1) {
  5596. ExitErrMsg(TRUE, "Could not fully-qualify log filename '%s'\n", LogName);
  5597. }
  5598. fpLog = fopen(FullLogName, "w");
  5599. if (!fpLog) {
  5600. ExitErrMsg(TRUE, "fopen(%s) failed\n", FullLogName);
  5601. }
  5602. if (!AddOpenFile(FullLogName, fpLog, NULL)) {
  5603. ExitErrMsg(FALSE, "AddOpenFile failed\n");
  5604. }
  5605. }
  5606. char *
  5607. UpdateLog(
  5608. char *pSrc,
  5609. PCGENSTATE pCGenState
  5610. )
  5611. {
  5612. FILE *fpOld;
  5613. BOOL bMore;
  5614. if (fpLog) {
  5615. fpOld = pCGenState->CGen->fp;
  5616. pCGenState->CGen->fp = fpLog;
  5617. bMore = TRUE;
  5618. } else {
  5619. fpOld = NULL;
  5620. bMore = FALSE;
  5621. }
  5622. pSrc = WriteMore(pSrc,pCGenState,bMore);
  5623. if (bMore) {
  5624. pCGenState->CGen->fp = fpOld;
  5625. fprintf(fpLog, "\n");
  5626. }
  5627. return pSrc;
  5628. }
  5629. /*
  5630. * ExtractCGenerate
  5631. */
  5632. BOOL ExtractCGenerate(char *pNames)
  5633. {
  5634. FILE *fp=NULL, *fpCpp=NULL;
  5635. size_t Len;
  5636. DWORD SizeFileName, SizeTempleName;
  5637. DWORD SizeFileNameCpp = 0;
  5638. char *pch;
  5639. char *pchColon, *pchComma;
  5640. PCGENERATE pCGen;
  5641. char *OutputBaseNameCpp = 0;
  5642. char FullOutputNameCpp[MAX_PATH+1];
  5643. char *OutputBaseName;
  5644. char FullOutputName[MAX_PATH+1];
  5645. char OutputName[MAX_PATH+1];
  5646. char OutputNameCpp[MAX_PATH+1];
  5647. char TempleName[MAX_PATH];
  5648. DbgPrintf("CGenerate: %s\n", pNames);
  5649. pchComma = strchr(pNames, ',');
  5650. pchColon = strchr(pNames, ':');
  5651. if (pchComma != NULL) {
  5652. pch = pchComma;
  5653. }
  5654. else {
  5655. pch = pchColon;
  5656. }
  5657. Len = pch - pNames;
  5658. if (!pch || !Len || Len >= sizeof(OutputName) - 1) {
  5659. return FALSE;
  5660. }
  5661. strncpy(OutputName, pNames, Len);
  5662. *(OutputName + Len) = '\0';
  5663. //
  5664. // Extract the CPP filename, and initialize iHandleCPP
  5665. //
  5666. OutputNameCpp[0] = '\0';
  5667. if (pchComma) {
  5668. size_t LenCpp;
  5669. LenCpp = pchColon - ++pchComma;
  5670. if (LenCpp >= sizeof(OutputNameCpp) - 1) {
  5671. return(FALSE);
  5672. }
  5673. if (LenCpp) {
  5674. iHandleCpp = 1; // use CPP macros
  5675. strncpy(OutputNameCpp, pchComma, LenCpp);
  5676. *(OutputNameCpp + LenCpp) = '\0';
  5677. }
  5678. else {
  5679. iHandleCpp = -1; // ignore CPP macros, and don't warn
  5680. }
  5681. Len += LenCpp + 1;
  5682. }
  5683. pNames += Len;
  5684. if (*pNames != ':') { // no template name!
  5685. return FALSE;
  5686. }
  5687. Len = GetFullPathName(OutputName,
  5688. sizeof(FullOutputName) - 1,
  5689. FullOutputName,
  5690. &OutputBaseName
  5691. );
  5692. if (Len >= sizeof(FullOutputName) - 1) {
  5693. return FALSE;
  5694. }
  5695. SizeFileName = Len + 1;
  5696. fp = fopen(FullOutputName, "w");
  5697. if (!fp) {
  5698. ExitErrMsg(TRUE, "fopen(%s) failed\n", FullOutputName);
  5699. }
  5700. if (!AddOpenFile(FullOutputName, fp, NULL)) {
  5701. ExitErrMsg(FALSE, "AddOpenFile failed\n");
  5702. }
  5703. if (fseek(fp, 0, SEEK_SET)) {
  5704. ExitErrMsg(TRUE, "ExtractCGenerate: fseek to 0 failed\n");
  5705. }
  5706. //
  5707. // Open the CPP file name
  5708. //
  5709. //if (iHandleCpp > 0) {
  5710. if (OutputNameCpp[0]) {
  5711. Len = GetFullPathName(OutputNameCpp,
  5712. sizeof(FullOutputNameCpp) - 1,
  5713. FullOutputNameCpp,
  5714. &OutputBaseNameCpp
  5715. );
  5716. if (!Len || (Len >= sizeof(FullOutputNameCpp) - 1)) {
  5717. return FALSE;
  5718. }
  5719. SizeFileNameCpp = Len + 1;
  5720. fpCpp = fopen(FullOutputNameCpp, "w");
  5721. if (!fpCpp) {
  5722. ExitErrMsg(TRUE, "fopen(%s) failed\n", FullOutputNameCpp);
  5723. }
  5724. if (!AddOpenFile(FullOutputNameCpp, fpCpp, NULL)) {
  5725. ExitErrMsg(FALSE, "AddOpenFile failed\n");
  5726. }
  5727. if (fseek(fpCpp, 0, SEEK_SET)) {
  5728. ExitErrMsg(TRUE, "ExtractCGenerate fseek #2 to 0 failed\n");
  5729. }
  5730. }
  5731. pch = GetNextToken(pNames);
  5732. if (pch == pNames || !*pch) {
  5733. return FALSE;
  5734. }
  5735. Len = CopyToken(TempleName, pch, sizeof(TempleName) - 1);
  5736. if (!Len || Len >= sizeof(TempleName) - 1) {
  5737. return FALSE;
  5738. }
  5739. SizeTempleName = Len + 1;
  5740. Len = sizeof(CGENERATE) + 1;
  5741. Len += SizeFileName + SizeTempleName + SizeFileNameCpp;
  5742. pCGen = GenHeapAlloc(Len);
  5743. if (!pCGen) {
  5744. ExitErrMsg(TRUE, "GenHeapAlloc(CGENERATE)");
  5745. }
  5746. memset(pCGen, 0, Len);
  5747. if (bDebug) {
  5748. setvbuf(fp, NULL, _IONBF, 0);
  5749. }
  5750. pCGen->fp = fp;
  5751. pCGen->fpC = fp;
  5752. strcpy(pCGen->TempleName, TempleName);
  5753. pCGen->FileNameC = pCGen->TempleName + SizeTempleName;
  5754. pCGen->FileBaseNameC = pCGen->FileNameC;
  5755. pCGen->FileBaseNameC += OutputBaseName - FullOutputName;
  5756. strcpy(pCGen->FileNameC, FullOutputName);
  5757. //
  5758. // Save the CPP filename, and file handle.
  5759. //
  5760. if (iHandleCpp > 0 && OutputNameCpp[0]) {
  5761. if (bDebug) {
  5762. setvbuf(fpCpp, NULL, _IONBF, 0);
  5763. }
  5764. pCGen->fpCpp = fpCpp;
  5765. pCGen->FileNameCpp = pCGen->FileNameC + SizeFileName;
  5766. pCGen->FileBaseNameCpp = pCGen->FileNameCpp;
  5767. pCGen->FileBaseNameCpp += OutputBaseNameCpp - FullOutputNameCpp;
  5768. strcpy(pCGen->FileNameCpp, FullOutputNameCpp);
  5769. }
  5770. InsertTailList(&CGenerateList, &pCGen->CGenerateEntry);
  5771. return TRUE;
  5772. }
  5773. /*
  5774. * ExtractTemples
  5775. *
  5776. */
  5777. BOOL ExtractTemples(char *FileName)
  5778. {
  5779. FILE *fp;
  5780. int FileSize;
  5781. BOOL bRet = FALSE;
  5782. char *pSrc;
  5783. char *pch;
  5784. size_t Len;
  5785. int CGenLen;
  5786. LPSTR pCCode[MAX_CODEBURST];
  5787. char Comment[MAX_PATH];
  5788. char IndLevel[MAX_PATH];
  5789. char TempleType[MAX_PATH];
  5790. char TempleName[MAX_PATH];
  5791. char CodeBurstName[MAX_PATH];
  5792. LPSTR Also[MAX_ALSO];
  5793. int AlsoCount;
  5794. LPSTR NoType[MAX_NOTYPE];
  5795. int NoTypeCount;
  5796. PLIST_ENTRY pCaseList;
  5797. char Line[1024];
  5798. int CodeBurstIndex;
  5799. TOKENTYPE tkDirection;
  5800. PTEMPLES tpl;
  5801. BOOL fFreeCCode = TRUE;
  5802. int i;
  5803. DbgPrintf("Template: %s\n", FileName);
  5804. fp = fopen(FileName, "r");
  5805. if (!fp) {
  5806. ExitErrMsg(TRUE, "fopen(%s) failed\n", FileName);
  5807. }
  5808. if (fseek(fp, 0, SEEK_END)) {
  5809. ExitErrMsg(TRUE, "fseek to EOF failed\n");
  5810. }
  5811. FileSize = ftell(fp);
  5812. if (fseek(fp, 0, SEEK_SET)) {
  5813. ExitErrMsg(TRUE, "fseek to 0 failed\n");
  5814. }
  5815. // Record the filename/line number information for error messages
  5816. TemplateFileName = FileName;
  5817. TemplateLine = 1;
  5818. if (!fgets(Line, sizeof(Line) - 1, fp)) {
  5819. if (ferror(fp)) {
  5820. ExitErrMsg(TRUE, "Failed to get Types from %s\n", FileName);
  5821. } else if (feof(fp)) {
  5822. ExitErrMsg(TRUE, "Premature EOF %s\n", FileName);
  5823. }
  5824. }
  5825. // reset the TempleType: no [TempleType] is active
  5826. *TempleType = '\0';
  5827. // reset all variables used within a [TempleType]
  5828. CGenLen = 0;
  5829. *IndLevel = 0;
  5830. *TempleName = '\0';
  5831. strcpy(Comment, "//");
  5832. memset(pCCode, 0, sizeof(LPSTR)*MAX_CODEBURST);
  5833. tkDirection = TK_EOS; // assume template handles all flavors of IN/OUT
  5834. AlsoCount=0;
  5835. NoTypeCount=0;
  5836. pCaseList = NULL;
  5837. // loop over all lines in the template file
  5838. do {
  5839. pSrc = Line;
  5840. // skip whitespace at the start of the line
  5841. while (*pSrc && isspace(*pSrc)) {
  5842. pSrc++;
  5843. }
  5844. // if at end-of-line or encountered ';' (comment-to-EOL), go to
  5845. // next line.
  5846. if (!*pSrc || *pSrc == ';') {
  5847. goto GetNextLine;
  5848. }
  5849. if (*pSrc == '[') {
  5850. // encountered new [TempleType]. If there was a previous template,
  5851. // add it now.
  5852. if (*TempleName &&
  5853. !AddTemple(TempleType, TempleName, Comment, IndLevel, pCCode, tkDirection, Also, AlsoCount, NoType, NoTypeCount, pCaseList)) {
  5854. ExitErrMsg(FALSE, "%s(%d) %s %s\n", TemplateFileName, TemplateLine, TempleType, pSrc);
  5855. }
  5856. // free the previous template's memory
  5857. if (fFreeCCode) {
  5858. for (i=0; i < MAX_CODEBURST; ++i) {
  5859. if (pCCode[i]) {
  5860. GenHeapFree(pCCode[i]);
  5861. }
  5862. }
  5863. }
  5864. fFreeCCode = TRUE;
  5865. // reset the vars used for each template
  5866. CGenLen = 0;
  5867. memset(pCCode, 0, sizeof(LPSTR)*MAX_CODEBURST);
  5868. *IndLevel = 0;
  5869. *TempleName = '\0';
  5870. strcpy(Comment, "//");
  5871. tkDirection = TK_EOS; // assume template handles all flavors of IN/OUT
  5872. pCaseList = NULL;
  5873. for (i=0; i<AlsoCount; ++i) {
  5874. GenHeapFree(Also[i]);
  5875. }
  5876. AlsoCount=0;
  5877. for (i=0; i<NoTypeCount; ++i) {
  5878. GenHeapFree(NoType[i]);
  5879. }
  5880. NoTypeCount=0;
  5881. // set up the new TempleType
  5882. pSrc++;
  5883. Len = CopyToken(TempleType, pSrc, sizeof(TempleType) - 1);
  5884. if (Len >= sizeof(TempleType) - 1) {
  5885. goto ETPLExit;
  5886. }
  5887. pch = pSrc + Len;
  5888. if (*pch != ']') {
  5889. *TempleType = '\0';
  5890. }
  5891. goto GetNextLine;
  5892. }
  5893. // if no active [TempleType], ignore the line
  5894. if (!*TempleType) {
  5895. goto GetNextLine;
  5896. }
  5897. // a [TempleType] is active. Scan for known property names
  5898. if ( ((pch = SkipKeyWord(pSrc, szTEMPLENAME)) != pSrc ||
  5899. (pch = SkipKeyWord(pSrc, szMACRONAME)) != pSrc ||
  5900. (pch = SkipKeyWord(pSrc, szTYPENAME)) != pSrc)
  5901. && *pch == '=') {
  5902. // found: TemplateName=
  5903. // or MacroName=
  5904. // or TypeName=
  5905. // They all mean the same thing.
  5906. // If a template is outstanding, add it now.
  5907. if (*TempleName &&
  5908. !AddTemple(TempleType, TempleName, Comment, IndLevel, pCCode, tkDirection, Also, AlsoCount, NoType, NoTypeCount, pCaseList)) {
  5909. ExitErrMsg(FALSE, "%s(%d) %s %s\n", TemplateFileName, TemplateLine, TempleType, pSrc);
  5910. }
  5911. // free the previous template's memory
  5912. if (fFreeCCode) {
  5913. for (i=0; i < MAX_CODEBURST; ++i) {
  5914. if (pCCode[i]) {
  5915. GenHeapFree(pCCode[i]);
  5916. }
  5917. }
  5918. }
  5919. fFreeCCode = TRUE;
  5920. // reset the vars used for each template
  5921. CGenLen = 0;
  5922. memset(pCCode, 0, sizeof(LPSTR)*MAX_CODEBURST);
  5923. *IndLevel = 0;
  5924. *TempleName = '\0';
  5925. tkDirection = TK_EOS; // assume template handles all flavors of IN/OUT
  5926. pCaseList = NULL;
  5927. for (i=0; i<AlsoCount; ++i) {
  5928. GenHeapFree(Also[i]);
  5929. }
  5930. AlsoCount=0;
  5931. for (i=0; i<NoTypeCount; ++i) {
  5932. GenHeapFree(NoType[i]);
  5933. }
  5934. NoTypeCount=0;
  5935. // copy in the new TemplateName
  5936. pch = GetNextToken(pch);
  5937. Len = sizeof(TempleName) - 1;
  5938. pSrc = TempleName;
  5939. while (isgraph(*pch) && Len--) {
  5940. *pSrc++ = *pch++;
  5941. }
  5942. if (Len == 0) {
  5943. // name too long
  5944. goto ETPLExit;
  5945. }
  5946. *pSrc = '\0';
  5947. } else if ((pch = SkipKeyWord(pSrc, szCOMMENT)) != pSrc &&
  5948. *pch == '=') {
  5949. // found: Comment=
  5950. pch = GetNextToken(pch);
  5951. Len = sizeof(Comment) - 1;
  5952. pSrc = Comment;
  5953. while (isgraph(*pch) && Len--) {
  5954. *pSrc++ = *pch++;
  5955. }
  5956. *pSrc = '\0';
  5957. } else if ( ((pch = SkipKeyWord(pSrc, szINDLEVEL)) != pSrc ||
  5958. (pch = SkipKeyWord(pSrc, szNUMARGS)) != pSrc)
  5959. && *pch == '=') {
  5960. // Found: IndLevel=
  5961. // or NumArgs=
  5962. // They mean the same thing
  5963. pch = GetNextToken(pch);
  5964. if (IsSeparator(*pch)) {
  5965. goto ETPLExit;
  5966. }
  5967. pSrc = pch;
  5968. Len = CopyToken(IndLevel, pSrc, sizeof(IndLevel) - 1);
  5969. pch += Len;
  5970. } else if ((pch = SkipKeyWord(pSrc, szDIRECTION)) != pSrc &&
  5971. *pch == '=') {
  5972. pch++;
  5973. // Found: Direction=
  5974. if (strncmp(pch, "IN OUT", 6) == 0) {
  5975. tkDirection = TK_INOUT;
  5976. pch += 6;
  5977. } else if (strncmp(pch, "IN", 2) == 0) {
  5978. tkDirection = TK_IN;
  5979. pch += 2;
  5980. } else if (strncmp(pch, "OUT", 3) == 0) {
  5981. tkDirection = TK_OUT;
  5982. pch += 3;
  5983. } else if (strncmp(pch, "none", 4) == 0) {
  5984. // this allows a type template to explicitly catch
  5985. // all pointer types which have no IN/OUT modifiers.
  5986. tkDirection = TK_NONE;
  5987. pch+=4;
  5988. } else {
  5989. goto ETPLExit;
  5990. }
  5991. } else if ((pch = SkipKeyWord(pSrc, szUSE)) != pSrc &&
  5992. *pch == '=') {
  5993. PLIST_ENTRY pHeadList;
  5994. char buffer[MAX_PATH];
  5995. // Found: Use=
  5996. pch++;
  5997. pHeadList = ListFromTempleType(TempleType);
  5998. if (!pHeadList) {
  5999. ExitErrMsg(FALSE, "%s(%d) Use= can only be used after a [Temple]\n", TemplateFileName, TemplateLine);
  6000. }
  6001. Len = CopyToken(buffer, pch, sizeof(buffer));
  6002. tpl = GetTemplate(pHeadList, buffer);
  6003. if (!tpl) {
  6004. ExitErrMsg(FALSE, "%s(%d) Use=%s: Template not found\n", TemplateFileName, TemplateLine, pch);
  6005. }
  6006. // copy the template back to our locals
  6007. strcpy(Comment, tpl->Comment);
  6008. sprintf(IndLevel, "%d", tpl->IndLevel);
  6009. tkDirection = tpl->tkDirection;
  6010. memcpy(pCCode, tpl->CodeBurst, sizeof(LPSTR)*MAX_CODEBURST);
  6011. fFreeCCode = FALSE; // Don't GenHeapFree() the pCCode array
  6012. // after adding this temple.
  6013. pch += Len;
  6014. } else if ((pch = SkipKeyWord(pSrc, szNOTYPE)) != pSrc &&
  6015. *pch == '=') {
  6016. char *t;
  6017. if (AlsoCount) {
  6018. ExitErrMsg(FALSE, "%s(%d) Cannot have both NoType= and Also= in the same template\n", TemplateFileName, TemplateLine);
  6019. }
  6020. // skip '=' and any leading spaces
  6021. do {
  6022. pch++;
  6023. if (*pch == '\0') {
  6024. goto ETPLExit;
  6025. }
  6026. } while (isspace(*pch) && *pch != '\0');
  6027. // get length of the NoType= name
  6028. t = pch;
  6029. while (isgraph(*t)) {
  6030. t++;
  6031. }
  6032. Len= t-pch;
  6033. // copy the name
  6034. t = GenHeapAlloc(Len + 1);
  6035. memcpy(t, pch, Len);
  6036. t[Len] = '\0';
  6037. if (NoTypeCount == MAX_NOTYPE) {
  6038. ExitErrMsg(FALSE, "%s(%d) Max. of %d NoType= clauses allowed. Also=%s\n", TemplateFileName, TemplateLine, MAX_ALSO, t);
  6039. }
  6040. NoType[NoTypeCount++] = t;
  6041. pch += Len;
  6042. } else if ((pch = SkipKeyWord(pSrc, szCASE)) != pSrc &&
  6043. *pch == '=') {
  6044. char *t;
  6045. PMACROARGSLIST pMArgsList = NULL;
  6046. PMLLISTENTRY pMLListEntry = NULL;
  6047. // skip '=' and any leading spaces
  6048. do {
  6049. pch++;
  6050. if (*pch == '\0') {
  6051. goto ETPLExit;
  6052. }
  6053. } while (isspace(*pch) && *pch != '\0');
  6054. // get length of the Case=
  6055. t = pch;
  6056. while (isgraph(*t)) {
  6057. t++;
  6058. }
  6059. Len= t-pch;
  6060. if (pCaseList == NULL) {
  6061. pCaseList = CheckHeapAlloc(sizeof(LIST_ENTRY));
  6062. InitializeListHead(pCaseList);
  6063. }
  6064. ParseMacroArgs(pch, Len, &pMArgsList);
  6065. pMLListEntry = CheckHeapAlloc(sizeof(MLLISTENTRY));
  6066. if (NULL == pMLListEntry) {
  6067. ExitErrMsg(FALSE, "Out of memory\n");
  6068. }
  6069. pMLListEntry->pMArgs = pMArgsList;
  6070. InsertTailList(pCaseList, &(pMLListEntry->ListEntry));
  6071. pch += Len;
  6072. } else if ((pch = SkipKeyWord(pSrc, szALSO)) != pSrc &&
  6073. *pch == '=') {
  6074. char *t;
  6075. if (NoTypeCount) {
  6076. ExitErrMsg(FALSE, "%s(%d) Cannot have both Also= and NoType= in the same template\n", TemplateFileName, TemplateLine);
  6077. }
  6078. // skip '=' and any leading spaces
  6079. do {
  6080. pch++;
  6081. if (*pch == '\0') {
  6082. goto ETPLExit;
  6083. }
  6084. } while (isspace(*pch) && *pch != '\0');
  6085. // get length of the Also= name
  6086. t = pch;
  6087. while (isgraph(*t)) {
  6088. t++;
  6089. }
  6090. Len= t-pch;
  6091. // copy the name
  6092. t = GenHeapAlloc(Len + 1);
  6093. memcpy(t, pch, Len);
  6094. t[Len] = '\0';
  6095. if (AlsoCount == MAX_ALSO) {
  6096. ExitErrMsg(FALSE, "%s(%d) Max. of %d Also= clauses allowed. Also=%s\n", TemplateFileName, TemplateLine, MAX_ALSO, t);
  6097. }
  6098. Also[AlsoCount++] = t;
  6099. pch += Len;
  6100. } else {
  6101. GetNextCodeBurst:
  6102. // grab the name, and if the next thing isn't '=', error out.
  6103. pch = GetNextToken(pSrc);
  6104. if (*pch != '=') {
  6105. goto ETPLExit;
  6106. }
  6107. Len = CopyToken(CodeBurstName, pSrc, pch-pSrc);
  6108. pch += Len;
  6109. // convert the name into an index
  6110. CodeBurstIndex = GetCodeBurstIndex(CodeBurstName);
  6111. if (pCCode[CodeBurstIndex]) {
  6112. // Two codebursts with the same name in this template
  6113. goto ETPLExit;
  6114. }
  6115. pCCode[CodeBurstIndex] = GenHeapAlloc(FileSize*2 + 1);
  6116. CGenLen = 0;
  6117. pSrc = pCCode[CodeBurstIndex];
  6118. while (fgets(pSrc, FileSize*2 - CGenLen, fp)) {
  6119. char buffer[MAX_PATH];
  6120. int len;
  6121. TemplateLine++;
  6122. len = CopyToken(buffer, pSrc, sizeof(buffer));
  6123. pch = pSrc;
  6124. if (len && pSrc[len] == '=') {
  6125. // The line starts with some keyword and is followed by
  6126. // an '=' sign.
  6127. if (strcmp(buffer, szCGENEND) == 0 ||
  6128. strcmp(buffer, "CGenEnd") == 0) {
  6129. // The string is 'End=' or 'CGenEnd='. The CodeBurst
  6130. // is done.
  6131. *pSrc = '\0';
  6132. CGenLen++;
  6133. pch += len+1;
  6134. break;
  6135. }
  6136. // See if it is the start of a new CodeBurst:
  6137. CodeBurstIndex = GetExistingCodeBurstIndex(buffer);
  6138. if (CodeBurstIndex != -1) {
  6139. strcpy(Line, pSrc);
  6140. *pSrc = '\0';
  6141. CGenLen++;
  6142. pSrc = Line;
  6143. goto GetNextCodeBurst;
  6144. }
  6145. }
  6146. Len = strlen(pSrc);
  6147. CGenLen += Len;
  6148. pSrc += Len;
  6149. }
  6150. if (!CGenLen) {
  6151. GenHeapFree(pCCode[CodeBurstIndex]);
  6152. pCCode[CodeBurstIndex] = NULL;
  6153. }
  6154. }
  6155. while (*pch && *pch != ';' && IsSeparator(*pch)) {
  6156. pch++;
  6157. }
  6158. if (*pch) {
  6159. if (*pch == ';') {
  6160. // comment to end-of-line
  6161. goto GetNextLine;
  6162. }
  6163. goto ETPLExit;
  6164. }
  6165. GetNextLine:
  6166. TemplateLine++;
  6167. } while (fgets(Line, sizeof(Line) - 1, fp));
  6168. // If there is an outstanding template when EOF is hit, add it now.
  6169. if (*TempleName &&
  6170. !AddTemple(TempleType, TempleName, Comment, IndLevel, pCCode, tkDirection, Also, AlsoCount, NoType, NoTypeCount, pCaseList)) {
  6171. ExitErrMsg(FALSE, "%s(%d) %s %s\n", TemplateFileName, TemplateLine, TempleType, pSrc);
  6172. }
  6173. if (!feof(fp) && ferror(fp)) {
  6174. ExitErrMsg(TRUE, "%s(%d) Read error: %s\n", TemplateFileName, TemplateLine, TempleName);
  6175. }
  6176. bRet = TRUE;
  6177. ETPLExit:
  6178. if (!bRet) {
  6179. ErrMsg("%s(%d) ETPL: Invalid Line <%s>\n%s\n", TemplateFileName, TemplateLine, pSrc, Line);
  6180. }
  6181. if (fFreeCCode) {
  6182. for (i=0; i < MAX_CODEBURST; ++i) {
  6183. if (pCCode[i]) {
  6184. GenHeapFree(pCCode[i]);
  6185. }
  6186. }
  6187. }
  6188. for (i=0; i<AlsoCount; ++i) {
  6189. GenHeapFree(Also[i]);
  6190. }
  6191. for (i=0; i<NoTypeCount; ++i) {
  6192. GenHeapFree(NoType[i]);
  6193. }
  6194. fclose(fp);
  6195. TemplateFileName = NULL;
  6196. return bRet;
  6197. }
  6198. PEXPORTSDEBUG
  6199. FindInExportsList(char *Name)
  6200. {
  6201. PLIST_ENTRY pNext;
  6202. PEXPORTSDEBUG pexportsdbg;
  6203. pNext = ExportsList.Flink;
  6204. while (pNext != &ExportsList) {
  6205. pexportsdbg = CONTAINING_RECORD(pNext, EXPORTSDEBUG, ExportsDbgEntry);
  6206. if (!strcmp(Name, pexportsdbg->ExportName)) {
  6207. return pexportsdbg;
  6208. }
  6209. pNext = pNext->Flink;
  6210. }
  6211. return NULL;
  6212. }
  6213. PLIST_ENTRY
  6214. ListFromTempleType(
  6215. char *TempleType
  6216. )
  6217. {
  6218. if (!TempleType || !*TempleType) {
  6219. return NULL;
  6220. }
  6221. if (!strcmp(TempleType, szIFUNC)) {
  6222. return &IFuncTempleList;
  6223. } else if (!strcmp(TempleType, szEFUNC)) {
  6224. return &EFuncTempleList;
  6225. } else if (!strcmp(TempleType, szTYPES)) {
  6226. return &TypeTempleList;
  6227. } else if (!strcmp(TempleType, szCODE)) {
  6228. return &CodeTempleList;
  6229. } else if (!strcmp(TempleType, szEFAST)) {
  6230. return &EFastTempleList;
  6231. } else if (!strcmp(TempleType, szMACROS)) {
  6232. return &MacroList;
  6233. } else if (!strcmp(TempleType, szFAILTYPES)) {
  6234. return &FailTempleList;
  6235. }
  6236. return NULL;
  6237. }
  6238. /*
  6239. * AddTemple
  6240. *
  6241. * worker function for ExtractTemple, to verify and store template.
  6242. */
  6243. #pragma optimize("", off)
  6244. BOOL
  6245. AddTemple(
  6246. char *TempleType,
  6247. char *TempleName,
  6248. char *Comment,
  6249. char *IndLevel,
  6250. char *pCCode[MAX_CODEBURST],
  6251. TOKENTYPE tkDirection,
  6252. char *Also[MAX_ALSO],
  6253. int AlsoCount,
  6254. char *NoType[MAX_NOTYPE],
  6255. int NoTypeCount,
  6256. PLIST_ENTRY pCaseList
  6257. )
  6258. {
  6259. PLIST_ENTRY pHeadList = NULL;
  6260. PTEMPLES ptpl;
  6261. char *pch;
  6262. int SizeCGen, SizeTempleName, SizeComment, SizeNoType;
  6263. int Len;
  6264. int i;
  6265. int AlsoIndex;
  6266. if (!*TempleName) {
  6267. return FALSE;
  6268. }
  6269. pHeadList = ListFromTempleType(TempleType);
  6270. if (!pHeadList) {
  6271. return FALSE;
  6272. }
  6273. SizeCGen = 0;
  6274. for (i=0; i<MAX_CODEBURST; ++i) {
  6275. SizeCGen++;
  6276. if (pCCode[i]) {
  6277. SizeCGen += strlen(pCCode[i]);
  6278. }
  6279. }
  6280. AlsoIndex=0;
  6281. for (;;) {
  6282. if (pHeadList != &TypeTempleList && GetTemplate(pHeadList, TempleName)) {
  6283. ExitErrMsg(FALSE, "Multiple templates are not allowed. TemplateName=%s, Type=%s\n", TempleName, TempleType);
  6284. }
  6285. SizeTempleName = strlen(TempleName) + 1;
  6286. SizeComment = strlen(Comment) + 1;
  6287. SizeNoType = 0;
  6288. for (i=0; i<NoTypeCount; ++i) {
  6289. SizeNoType += strlen(NoType[i])+1;
  6290. }
  6291. Len = SizeCGen + SizeTempleName + SizeComment + SizeNoType;
  6292. Len += sizeof(TEMPLES);
  6293. ptpl = GenHeapAlloc(Len);
  6294. if (!ptpl) {
  6295. ExitErrMsg(TRUE, "GenHeapAlloc(TEMPLE)");
  6296. }
  6297. memset(ptpl, 0, Len);
  6298. ptpl->IndLevel = strtoul(IndLevel, &pch, 10);
  6299. ptpl->tkDirection = tkDirection;
  6300. Len = 0;
  6301. ptpl->Name = ptpl->Buffer;
  6302. strcpy(ptpl->Name, TempleName);
  6303. Len += SizeTempleName;
  6304. ptpl->Comment = ptpl->Buffer + Len;
  6305. strcpy(ptpl->Comment, Comment);
  6306. Len += SizeComment;
  6307. for (i=0; i<MAX_CODEBURST; ++i) {
  6308. if (pCCode[i]) {
  6309. //
  6310. // Copy the code for this codeburst name
  6311. //
  6312. ptpl->CodeBurst[i] = ptpl->Buffer + Len;
  6313. Len++;
  6314. strcpy(ptpl->CodeBurst[i], pCCode[i]);
  6315. Len += strlen(pCCode[i]);
  6316. if (g_fLessTrailingWhitespace)
  6317. StripTrailingWhitespaceFromString(ptpl->CodeBurst[i]);
  6318. }
  6319. }
  6320. for (i=0; i<NoTypeCount; ++i) {
  6321. ptpl->NoTypes[i] = ptpl->Buffer + Len;
  6322. Len++;
  6323. strcpy(ptpl->NoTypes[i], NoType[i]);
  6324. Len += strlen(NoType[i]);
  6325. }
  6326. ptpl->pCaseList = pCaseList;
  6327. InsertTailList(pHeadList, &ptpl->TempleEntry);
  6328. if (bDebug && Len >= SizeCGen+SizeTempleName+SizeComment+SizeNoType) {
  6329. ExitErrMsg(FALSE, "Buffer overrun in AddTemple! Heap is trashed! ptpl=%x\n", ptpl);
  6330. }
  6331. if (bDebug) {
  6332. DumpTemplate(ptpl, stdout);
  6333. }
  6334. if (AlsoIndex == AlsoCount) {
  6335. break;
  6336. }
  6337. // there are Also= lines, add those template, too
  6338. strcpy(TempleName, Also[AlsoIndex]);
  6339. AlsoIndex++;
  6340. }
  6341. return TRUE;
  6342. }
  6343. #pragma optimize("", on)
  6344. /*
  6345. *
  6346. */
  6347. void DumpTemplate(PTEMPLES ptpl, FILE *fp)
  6348. {
  6349. int i;
  6350. fprintf(fp,"Temple: %d Name<%s>\n",
  6351. ptpl->IndLevel,
  6352. ptpl->Name
  6353. );
  6354. for (i=0; i<MAX_CODEBURST; ++i) {
  6355. if (CodeBursts[i].Name) {
  6356. fprintf(fp,"%s(%d) Temple: %s<%s>\n", TemplateFileName, TemplateLine, CodeBursts[i].Name, ptpl->CodeBurst[i]);
  6357. }
  6358. }
  6359. }
  6360. ULONG
  6361. EndianSwitch(
  6362. PULONG pul
  6363. )
  6364. {
  6365. ULONG NewValue;
  6366. PBYTE pbValue = (PBYTE)pul;
  6367. PBYTE pbNewValue = (PBYTE) &NewValue;
  6368. *pbNewValue++ = *(pbValue + 3);
  6369. *pbNewValue++ = *(pbValue + 2);
  6370. *pbNewValue++ = *(pbValue + 1);
  6371. *pbNewValue = *pbValue;
  6372. return NewValue;
  6373. }
  6374. /* MapViewDll
  6375. *
  6376. * Creates a Mapped view of a Dll and intializes
  6377. * Dll global variables for easy access to the Export Directory
  6378. *
  6379. * DllMappedBase
  6380. * DllRvaOffset
  6381. * DllExportDir
  6382. * DllExportDirSize
  6383. * DllFunctions
  6384. * DllNameOrdinals
  6385. * DllNameTable
  6386. *
  6387. *
  6388. */
  6389. BOOL MapViewDll(char *DllName)
  6390. {
  6391. ULONG_PTR RvaOffset;
  6392. HANDLE hFile;
  6393. HANDLE hMapFile;
  6394. PVOID MappedBase;
  6395. PIMAGE_EXPORT_DIRECTORY ExportDir;
  6396. ULONG ExportDirSize;
  6397. //
  6398. // open and map the file to get the exports info
  6399. //
  6400. hFile = CreateFile(DllName,
  6401. GENERIC_READ,
  6402. FILE_SHARE_READ,
  6403. NULL,
  6404. OPEN_EXISTING,
  6405. 0,
  6406. NULL
  6407. );
  6408. if (hFile == INVALID_HANDLE_VALUE) {
  6409. ErrMsg("MapViewDll CreateFile(%s) gle %d\n", DllName, GetLastError());
  6410. return FALSE;
  6411. }
  6412. hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0,NULL);
  6413. if (!hMapFile) {
  6414. ErrMsg("MapViewDll CreateFileMapping(%s) gle %d\n", DllName, GetLastError());
  6415. return FALSE;
  6416. }
  6417. MappedBase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
  6418. if (!MappedBase) {
  6419. ErrMsg("MapViewDll MapViewOfFile(%s) gle %d\n", DllName, GetLastError());
  6420. return FALSE;
  6421. }
  6422. ExportDir = ImageDirectoryEntryToData( MappedBase,
  6423. TRUE,
  6424. IMAGE_DIRECTORY_ENTRY_EXPORT,
  6425. &ExportDirSize
  6426. );
  6427. if (!ExportDir) {
  6428. ErrMsg("MapViewDll ImageDirectoryEntryToData=NULL\n");
  6429. return FALSE;
  6430. }
  6431. //
  6432. // Initialize the global variables.
  6433. //
  6434. RvaOffset = (ULONG_PTR)ExportDir - (ULONG_PTR)MappedBase;
  6435. ExportDir = ImageDirectoryEntryToData( MappedBase,
  6436. FALSE,
  6437. IMAGE_DIRECTORY_ENTRY_EXPORT,
  6438. &ExportDirSize
  6439. );
  6440. if (!ExportDir) {
  6441. ErrMsg("MapViewDll ImageDirectoryEntryToData=NULL on the second call\n");
  6442. return FALSE;
  6443. }
  6444. DllExportDirSize = ExportDirSize;
  6445. DllMappedBase = MappedBase;
  6446. DllRvaOffset = RvaOffset;
  6447. DllExportDir = ExportDir;
  6448. DllFunctions = (PULONG)((ULONG_PTR)ExportDir +
  6449. (ULONG_PTR)ExportDir->AddressOfFunctions - RvaOffset
  6450. );
  6451. DllNameTable = (PULONG)((ULONG_PTR)ExportDir +
  6452. (ULONG_PTR)ExportDir->AddressOfNames - RvaOffset
  6453. );
  6454. DllNameOrdinals = (PUSHORT)((ULONG_PTR)ExportDir +
  6455. (ULONG_PTR)ExportDir->AddressOfNameOrdinals - RvaOffset
  6456. );
  6457. fprintf(stdout,
  6458. "Name %s Base %x Ver %x.%x NumberOfFunctions %x NumberOfNames %x\n",
  6459. (PCHAR)((ULONG_PTR)ExportDir + (ULONG_PTR)ExportDir->Name - RvaOffset),
  6460. ExportDir->Base,
  6461. (ULONG)ExportDir->MajorVersion,
  6462. (ULONG)ExportDir->MinorVersion,
  6463. ExportDir->NumberOfFunctions,
  6464. ExportDir->NumberOfNames
  6465. );
  6466. return TRUE;
  6467. }
  6468. ULONG
  6469. DllOrdinalByName(
  6470. char *ExportName
  6471. )
  6472. {
  6473. PULONG pNames;
  6474. ULONG NumNames;
  6475. PUSHORT pNameOrdinals;
  6476. char *Name;
  6477. pNames = DllNameTable;
  6478. pNameOrdinals = DllNameOrdinals;
  6479. NumNames = DllExportDir->NumberOfNames;
  6480. while (NumNames--) {
  6481. Name = (char *)((ULONG_PTR)DllExportDir + *pNames - DllRvaOffset);
  6482. if (!strcmp(Name, ExportName)) {
  6483. return *pNameOrdinals + DllExportDir->Base;
  6484. }
  6485. pNames++;
  6486. pNameOrdinals++;
  6487. }
  6488. return 0;
  6489. }
  6490. /* MapViewImplib
  6491. *
  6492. * Creates a Mapped view of an import library and intializes
  6493. * ImpLib global variables for access to symbols in the first
  6494. * special linker member.
  6495. *
  6496. * ImplibMappedBase
  6497. * ImplibNumSymbols
  6498. * ImplibSymbolMembers
  6499. * ImplibSymbolNames
  6500. *
  6501. */
  6502. BOOL MapViewImplib(char *LibName)
  6503. {
  6504. HANDLE hFile;
  6505. HANDLE hMapFile;
  6506. PBYTE MappedBase;
  6507. PBYTE VirtualOffset;
  6508. ULONG MemberSize;
  6509. PIMAGE_ARCHIVE_MEMBER_HEADER ArchiveMemberHeader;
  6510. //
  6511. // open and map the file.
  6512. //
  6513. hFile = CreateFile(LibName,
  6514. GENERIC_READ,
  6515. FILE_SHARE_READ,
  6516. NULL,
  6517. OPEN_EXISTING,
  6518. 0,
  6519. NULL
  6520. );
  6521. if (hFile == INVALID_HANDLE_VALUE) {
  6522. ErrMsg("MapViewImplib CreateFile(%s) gle %d\n", LibName, GetLastError());
  6523. return FALSE;
  6524. }
  6525. hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0,NULL);
  6526. if (!hMapFile) {
  6527. ErrMsg("MapViewImplib CreateFileMapping(%s) gle %d\n", LibName, GetLastError());
  6528. return FALSE;
  6529. }
  6530. MappedBase = (PBYTE)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
  6531. if (!MappedBase) {
  6532. ErrMsg("MapViewImplib MapViewOfFile(%s) gle %d\n", LibName, GetLastError());
  6533. return FALSE;
  6534. }
  6535. //
  6536. // Verify the file is an archive
  6537. //
  6538. if (memcmp(MappedBase, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) {
  6539. ErrMsg("MapViewImplib IMAGE_ARCHIVE_START_SIZE invalid(%s)\n", LibName);
  6540. return FALSE;
  6541. }
  6542. VirtualOffset = MappedBase + IMAGE_ARCHIVE_START_SIZE;
  6543. ArchiveMemberHeader = (PIMAGE_ARCHIVE_MEMBER_HEADER) VirtualOffset;
  6544. if (sscanf((char *) ArchiveMemberHeader->Size, "%ld", &MemberSize) != 1) {
  6545. ErrMsg("MapViewImplib ArchiveMemberHeader->Size '%s' corrupt\n", (char *) ArchiveMemberHeader->Size);
  6546. return FALSE;
  6547. }
  6548. //
  6549. // Verify first special linker member exists (name == "\\")
  6550. //
  6551. if (memcmp(ArchiveMemberHeader->Name, IMAGE_ARCHIVE_LINKER_MEMBER, sizeof(ArchiveMemberHeader->Name))) {
  6552. ErrMsg("MapViewImplib first special linker member missing (%s)\n", LibName);
  6553. return FALSE;
  6554. }
  6555. //
  6556. // First Linker Member format (Big endian!)
  6557. // NumberOfSymbols, 4 bytes
  6558. // Offsets, 4 bytes * NumSymbols
  6559. // StringTable NumSymbols == NumStrings
  6560. //
  6561. VirtualOffset += sizeof(IMAGE_ARCHIVE_MEMBER_HEADER);
  6562. ImplibNumSymbols = EndianSwitch((PULONG)VirtualOffset);
  6563. VirtualOffset += 4;
  6564. ImplibSymbolMembers = (PULONG)VirtualOffset;
  6565. VirtualOffset += ImplibNumSymbols * sizeof(ULONG);
  6566. ImplibSymbolNames = (PCHAR)VirtualOffset;
  6567. ImplibMappedBase = MappedBase;
  6568. fprintf(stdout, "Implib: %s Base %p\n", LibName, ImplibMappedBase);
  6569. return TRUE;
  6570. }
  6571. BOOL
  6572. ExtractMember(
  6573. ULONG MemberOffset,
  6574. PULONG Ordinal,
  6575. BOOLEAN *Data
  6576. )
  6577. {
  6578. PIMAGE_FILE_HEADER ImageFileHeader;
  6579. PBYTE VirtualOffset;
  6580. BOOL Idata5Found, TextFound;
  6581. VirtualOffset = (PBYTE)ImplibMappedBase + MemberOffset;
  6582. VirtualOffset += sizeof(IMAGE_ARCHIVE_MEMBER_HEADER);
  6583. ImageFileHeader = (PIMAGE_FILE_HEADER) VirtualOffset;
  6584. *Ordinal = 0;
  6585. Idata5Found = FALSE;
  6586. TextFound = FALSE;
  6587. if (ImageFileHeader->Machine == 0 &&
  6588. ImageFileHeader->NumberOfSections == 0xffff) {
  6589. //
  6590. // VC6 format import lib found.
  6591. //
  6592. PVC6_IMAGE_IMPORT_HEADER pHdr;
  6593. pHdr = (PVC6_IMAGE_IMPORT_HEADER)ImageFileHeader;
  6594. if (pHdr->NameType == IMPORT_ORDINAL) {
  6595. //
  6596. // pHdr->wOrdinal specifies the ordinal for this import.
  6597. //
  6598. *Ordinal = 0x80000000 | (ULONG)pHdr->Ordinal;
  6599. }
  6600. if (pHdr->Type == IMPORT_DATA) {
  6601. //
  6602. // This is a data import
  6603. //
  6604. *Data = TRUE;
  6605. }
  6606. Idata5Found = TRUE;
  6607. } else {
  6608. //
  6609. // Pre-VC6 import lib.
  6610. //
  6611. ULONG NumSections;
  6612. ULONG UNALIGNED *RawDataPointer;
  6613. IMAGE_SECTION_HEADER UNALIGNED *ImageSectionHeader;
  6614. NumSections = ImageFileHeader->NumberOfSections;
  6615. //
  6616. // Carefull, librarian doesn't align the Image section header according
  6617. // to normal rules for images.
  6618. //
  6619. VirtualOffset += sizeof(IMAGE_FILE_HEADER) + ImageFileHeader->SizeOfOptionalHeader;
  6620. ImageSectionHeader = (IMAGE_SECTION_HEADER UNALIGNED *)VirtualOffset;
  6621. while (NumSections--) {
  6622. //
  6623. // Implib provides .idata5, and .idata4 (duplicate) which
  6624. // contains the ordinal number with the hi bit set if it
  6625. // was specified in the module definition file. Otherwise
  6626. // the ordinal number is not specified in the implib.
  6627. //
  6628. if (!Idata5Found &&
  6629. !strncmp(ImageSectionHeader->Name, szIDATA5, sizeof(szIDATA5)-1)) {
  6630. //
  6631. // Carefull, librarian doesn't align the begining of raw data
  6632. // according to normal rules for images.
  6633. //
  6634. RawDataPointer = (ULONG UNALIGNED *)((PBYTE)ImageFileHeader + ImageSectionHeader->PointerToRawData);
  6635. if (*RawDataPointer & 0x80000000) {
  6636. *Ordinal = *RawDataPointer;
  6637. }
  6638. Idata5Found = TRUE;
  6639. } else if (!TextFound &&
  6640. !strncmp(ImageSectionHeader->Name, szTEXT, sizeof(szTEXT)-1)) {
  6641. TextFound = TRUE;
  6642. }
  6643. ImageSectionHeader++;
  6644. }
  6645. *Data = (!TextFound) ? TRUE : FALSE; // if no text section, must be data export
  6646. }
  6647. return Idata5Found;
  6648. }
  6649. BOOL
  6650. InitExportDebug(
  6651. PEXPORTSDEBUG ExportDebug,
  6652. char *SymbolName,
  6653. ULONG SymbolMember
  6654. )
  6655. {
  6656. ULONG_PTR Forward;
  6657. ULONG OrdinalIndex;
  6658. char *pch = SymbolName; // we assume __implib_ prefix not present
  6659. //
  6660. // C fn begins with "_"
  6661. // C++ fn begins with "?"
  6662. // Data export begins with "??_C" in real symbols,
  6663. // but in implib looks a C function
  6664. //
  6665. if (*pch == '?') {
  6666. ExportDebug->CplusDecoration = pch;
  6667. DbgPrintf("C++ export %s\n", SymbolName);
  6668. }
  6669. else {
  6670. ExportDebug->CplusDecoration = NULL;
  6671. }
  6672. //
  6673. // Copy out the ExportName.
  6674. //
  6675. if (*pch == '_' || *pch == '?' || *pch == '@') {
  6676. pch++; // skip lead char (underscor, qmark)
  6677. }
  6678. strcpy(ExportDebug->ExportName, pch);
  6679. pch = strchr(ExportDebug->ExportName, '@');
  6680. if (SymbolName[0] == '?' && SymbolName[1] == '?') {
  6681. //
  6682. // Found a "real" C++ name: a mangled version of
  6683. // "classname::membername". Use the fully-mangled function name,
  6684. // instead of the name with the leading '?' stripped, and don't
  6685. // truncate after the '@'.
  6686. //
  6687. strcpy(ExportDebug->ExportName, SymbolName);
  6688. pch = NULL;
  6689. }
  6690. if (pch && ExportDebug->CplusDecoration && pch[1] != '@') {
  6691. //
  6692. // This export is '?membername@classname@@...'. Don't truncate!
  6693. //
  6694. strcpy(ExportDebug->ExportName, SymbolName);
  6695. pch = NULL;
  6696. }
  6697. if (pch && !bNoFuzzyLogic) { // truncate the symbol from ExportName
  6698. *pch = '\0';
  6699. }
  6700. //
  6701. // Get the decoration, for synthetic args
  6702. // cdecl has no decoration
  6703. // stdcall has total arg size
  6704. //
  6705. if (pch && !ExportDebug->CplusDecoration) {
  6706. ExportDebug->ArgsSize = strtol(pch + 1, NULL, 10);
  6707. }
  6708. else {
  6709. ExportDebug->ArgsSize = -1;
  6710. }
  6711. //
  6712. // Fetch the ordinal from the implib. In an Implib the ordinal
  6713. // only appears if an ordinal is specifed in the def file.
  6714. //
  6715. if (!ExtractMember(SymbolMember, &ExportDebug->Ordinal, &ExportDebug->Data)) {
  6716. ErrMsg("InitExportDebug: %s Member not found\n", SymbolName);
  6717. return FALSE;
  6718. }
  6719. if (ExportDebug->Data) {
  6720. DbgPrintf("DATA export %s\n", SymbolName);
  6721. }
  6722. //
  6723. // If we don't yet have an ordinal, search the ExportNameTable
  6724. // for the Ordinal number. Note that Ordinals which *must* appear
  6725. // in generated def files have the hi-bit set!
  6726. //
  6727. if (!ExportDebug->Ordinal) {
  6728. ExportDebug->Ordinal = DllOrdinalByName(ExportDebug->ExportName);
  6729. if (!ExportDebug->Ordinal) {
  6730. ErrMsg("InitExportDebug: %s Ordinal not found\n", SymbolName);
  6731. return FALSE;
  6732. }
  6733. }
  6734. //
  6735. // Look up function using ordinal as index to function table.
  6736. //
  6737. OrdinalIndex = IMPORDINAL(ExportDebug->Ordinal) - DllExportDir->Base;
  6738. ExportDebug->Function = *(DllFunctions + OrdinalIndex);
  6739. //
  6740. // Check for references forwarded externally, we only need
  6741. // external forwards which are really internal forwards.
  6742. //
  6743. // e.g rpcrt4.dll has following def file entries:
  6744. //
  6745. // I_RpcBindingInqDynamicEndpoint=RPCRT4.I_RpcBindingInqDynamicEndpointW
  6746. // I_RpcBindingInqDynamicEndpointW
  6747. //
  6748. // Our thunk dll will use the following:
  6749. //
  6750. // I_RpcBindingInqDynamicEndpoint=I_RpcBindingInqDynamicEndpointW
  6751. // I_RpcBindingInqDynamicEndpointW
  6752. //
  6753. // It is important to strip the "rpcrt4." as this adds an extra
  6754. // loader reference to rpcrt4.dll.
  6755. //
  6756. //
  6757. ExportDebug->ExtForward = NULL;
  6758. Forward = (ULONG_PTR)DllExportDir + ExportDebug->Function - DllRvaOffset;
  6759. if (Forward > (ULONG_PTR)DllExportDir &&
  6760. Forward < (ULONG_PTR)DllExportDir + DllExportDirSize)
  6761. {
  6762. char *pSrc;
  6763. pSrc = (char *) Forward;
  6764. pch = DllBaseName;
  6765. while (*pSrc && *pSrc != '.' && toupper(*pSrc) == toupper(*pch)) {
  6766. pSrc++;
  6767. pch++;
  6768. }
  6769. if (*pSrc == *pch) {
  6770. ExportDebug->ExtForward = pSrc + 1;
  6771. }
  6772. }
  6773. DbgPrintf("%4.1d %8.1x(%4.1d) %8.1x %s(%s)\n",
  6774. ExportDebug->ArgsSize,
  6775. ExportDebug->Ordinal,
  6776. IMPORDINAL(ExportDebug->Ordinal),
  6777. ExportDebug->Function,
  6778. ExportDebug->ExportName,
  6779. ExportDebug->ExtForward ? ExportDebug->ExtForward : ""
  6780. );
  6781. return TRUE;
  6782. }
  6783. /*
  6784. * SetInternalForwards
  6785. *
  6786. *
  6787. *
  6788. */
  6789. void
  6790. SetInternalForwards(void)
  6791. {
  6792. PLIST_ENTRY NextExport;
  6793. PEXPORTSDEBUG ExportDebug;
  6794. //
  6795. // check each export in the list for multiple exports to same function.
  6796. // For each set of internal forwards identify which export defines the api,
  6797. // and save this in the IntForward field.
  6798. //
  6799. NextExport= ExportsList.Flink;
  6800. while (NextExport != &ExportsList) {
  6801. ExportDebug = CONTAINING_RECORD(NextExport,
  6802. EXPORTSDEBUG,
  6803. ExportsDbgEntry
  6804. );
  6805. if (ExportDebug->Function &&
  6806. !ExportDebug->ExtForward &&
  6807. !ExportDebug->IntForward)
  6808. {
  6809. PLIST_ENTRY Next;
  6810. PEXPORTSDEBUG pexdbg;
  6811. PEXPORTSDEBUG KnownApi =NULL;
  6812. int ArgSize = ExportDebug->ArgsSize;
  6813. //
  6814. // Walk the rest of the list to find first duplicate function
  6815. //
  6816. Next = NextExport->Flink;
  6817. while (Next != &ExportsList) {
  6818. pexdbg = CONTAINING_RECORD(Next,
  6819. EXPORTSDEBUG,
  6820. ExportsDbgEntry
  6821. );
  6822. if (pexdbg->Function == ExportDebug->Function) {
  6823. if (pexdbg->ArgsSize >= 0) {
  6824. ArgSize = pexdbg->ArgsSize;
  6825. }
  6826. break;
  6827. }
  6828. Next = Next->Flink;
  6829. }
  6830. if (Next != &ExportsList) {
  6831. //
  6832. // We found one dup function. Temporarily link together this set
  6833. // of dup functions using the IntForward field, and determine
  6834. // the first KnownApi.
  6835. //
  6836. if (GetNameFromTypesList(FuncsList, ExportDebug->ExportName)) {
  6837. KnownApi = ExportDebug;
  6838. }
  6839. do {
  6840. pexdbg = CONTAINING_RECORD(Next,
  6841. EXPORTSDEBUG,
  6842. ExportsDbgEntry
  6843. );
  6844. if (pexdbg->Function == ExportDebug->Function) {
  6845. pexdbg->IntForward = ExportDebug->IntForward;
  6846. ExportDebug->IntForward = pexdbg;
  6847. if (pexdbg->ArgsSize >= 0) {
  6848. ArgSize = pexdbg->ArgsSize;
  6849. }
  6850. if (!KnownApi &&
  6851. GetNameFromTypesList(FuncsList, pexdbg->ExportName))
  6852. {
  6853. KnownApi = pexdbg;
  6854. }
  6855. }
  6856. Next = Next->Flink;
  6857. } while (Next != &ExportsList);
  6858. //
  6859. // If we found multiple entries, walk the temp links, and insert
  6860. // the KnownApi, which is used to define the api. If we didn't
  6861. // find a known api, use ExportDebug, and hope for the best
  6862. // (since its not known).
  6863. //
  6864. if (!KnownApi) {
  6865. KnownApi = ExportDebug;
  6866. }
  6867. pexdbg = ExportDebug;
  6868. while (pexdbg) {
  6869. PEXPORTSDEBUG NextForward;
  6870. NextForward = pexdbg->IntForward;
  6871. pexdbg->IntForward = KnownApi;
  6872. pexdbg->ArgsSize = ArgSize;
  6873. DbgPrintf("IntForward: %s to %s\n",
  6874. pexdbg->ExportName,
  6875. KnownApi->ExportName
  6876. );
  6877. pexdbg = NextForward;
  6878. }
  6879. }
  6880. }
  6881. NextExport = NextExport->Flink;
  6882. }
  6883. }
  6884. /*
  6885. * ExtractExports -
  6886. *
  6887. * reads the exports debug info from a dll,
  6888. * and builds the exports list.
  6889. *
  6890. */
  6891. BOOL ExtractExports(void)
  6892. {
  6893. ULONG NumNames;
  6894. PULONG pNames;
  6895. PUSHORT pNameOrdinals;
  6896. PULONG ImpSymbolMember;
  6897. PCHAR ImpSymbolName;
  6898. EXPORTSDEBUG ExportDebug;
  6899. char ExportName[MAX_PATH+1];
  6900. //
  6901. // For each "__imp_" in the implib, gather name, symbol and ordinal
  6902. // and determine its forward status. This will pick up all exports
  6903. // except those which are marked "PRIVATE".
  6904. //
  6905. NumNames = ImplibNumSymbols;
  6906. ImpSymbolMember = ImplibSymbolMembers;
  6907. ImpSymbolName = ImplibSymbolNames;
  6908. while (NumNames--) {
  6909. if (!strncmp(szIMPPREFIX, ImpSymbolName, sizeof(szIMPPREFIX) - 1)) {
  6910. memset(&ExportDebug, 0, sizeof(ExportDebug));
  6911. ExportDebug.ApiPlatform = API_ALL;
  6912. ExportDebug.ExportName = ExportName;
  6913. if (!InitExportDebug(&ExportDebug,
  6914. ImpSymbolName + sizeof(szIMPPREFIX) - 1,
  6915. EndianSwitch(ImpSymbolMember)
  6916. ))
  6917. {
  6918. return FALSE;
  6919. }
  6920. if (!AddToExportsList(&ExportDebug)) {
  6921. return FALSE;
  6922. }
  6923. }
  6924. ImpSymbolMember++;
  6925. ImpSymbolName += strlen(ImpSymbolName) + 1;
  6926. }
  6927. //
  6928. // Search the Export name table for exports which haven't been added yet.
  6929. // These are "PRIVATE" exports with names. We will still be missing
  6930. // exports which are "PRIVATE NONAME", and we won't have symbolic info
  6931. // for the private named exports.
  6932. //
  6933. NumNames = DllExportDir->NumberOfNames;
  6934. pNames = DllNameTable;
  6935. pNameOrdinals = DllNameOrdinals;
  6936. while (NumNames--) {
  6937. memset(&ExportDebug, 0, sizeof(ExportDebug));
  6938. ExportDebug.Ordinal = *pNameOrdinals + DllExportDir->Base;
  6939. ExportDebug.Ordinal |= 0x80000000;
  6940. ExportDebug.Function = *(DllFunctions + *pNameOrdinals);
  6941. ExportDebug.ExportName = (char *)((ULONG_PTR)DllExportDir + *pNames - DllRvaOffset);
  6942. ExportDebug.ApiPlatform = API_ALL;
  6943. if (!FindInExportsList(ExportDebug.ExportName)) {
  6944. ULONG_PTR Forward;
  6945. char *pch;
  6946. //
  6947. // Check for references forwarded externally, we only need
  6948. // external forwards which are really internal forwards.
  6949. //
  6950. ExportDebug.ExtForward = NULL;
  6951. Forward = (ULONG_PTR)DllExportDir + ExportDebug.Function - DllRvaOffset;
  6952. if (Forward > (ULONG_PTR)DllExportDir &&
  6953. Forward < (ULONG_PTR)DllExportDir + DllExportDirSize)
  6954. {
  6955. char *pSrc;
  6956. pSrc = (char *)Forward;
  6957. pch = DllBaseName;
  6958. while (*pSrc && *pSrc != '.' && *pSrc == *pch) {
  6959. pSrc++;
  6960. pch++;
  6961. }
  6962. if (*pSrc == '.' && *pSrc == *pch) {
  6963. ExportDebug.ExtForward = pSrc + 1;
  6964. }
  6965. }
  6966. //
  6967. // Check for decorations embedded in the exportname
  6968. //
  6969. pch = strchr(ExportDebug.ExportName, '@');
  6970. if (pch++ && *pch != '@') {
  6971. ExportDebug.ArgsSize = strtol(pch, NULL, 10);
  6972. }
  6973. else {
  6974. ExportDebug.ArgsSize = -1;
  6975. }
  6976. ExportDebug.PrivateNamed = TRUE;
  6977. DbgPrintf("Private Named Export: %4.1d %8.1x(%4.1d) %8.1x %s(%s)\n",
  6978. ExportDebug.ArgsSize,
  6979. ExportDebug.Ordinal,
  6980. IMPORDINAL(ExportDebug.Ordinal),
  6981. ExportDebug.Function,
  6982. ExportDebug.ExportName,
  6983. ExportDebug.ExtForward ? ExportDebug.ExtForward : ""
  6984. );
  6985. if (!AddToExportsList(&ExportDebug)) {
  6986. return FALSE;
  6987. }
  6988. }
  6989. // advance to next name\ordinal
  6990. pNames++;
  6991. pNameOrdinals++;
  6992. }
  6993. return TRUE;
  6994. }
  6995. /*
  6996. ExtractServicesTab-
  6997. Used as a replacement to ExtractXpt. Extracts file list from a services.tab
  6998. file as used in the ntos project.
  6999. */
  7000. void ExtractServicesTab(char *pch)
  7001. {
  7002. FILE *fp;
  7003. char pTemp;
  7004. EXPORTSDEBUG ExportDebug;
  7005. char Line[MAX_PATH];
  7006. char ExportName[MAX_PATH];
  7007. char *ApiName;
  7008. char *Prepend;
  7009. char *FileName;
  7010. size_t len, PrependLen;
  7011. //extract filename and optional prepend name
  7012. FileName = pch;
  7013. while(*pch != ':' && *pch != '\0')
  7014. pch++;
  7015. pTemp = *pch;
  7016. *pch = '\0';
  7017. if (pTemp == ':') {
  7018. pch++;
  7019. Prepend = pch;
  7020. while(*pch != '\0') {
  7021. pch++;
  7022. }
  7023. PrependLen = pch-Prepend;
  7024. }
  7025. else {
  7026. Prepend = pch;
  7027. PrependLen = 0;
  7028. }
  7029. if (PrependLen > MAX_PATH - 1) {
  7030. ExitErrMsg(FALSE, "ExSt: Text to prepend to functions names is too long\n");
  7031. }
  7032. memcpy(ExportName, Prepend, PrependLen);
  7033. DbgPrintf("ExST: %s,%s\n", FileName, Prepend);
  7034. fp = fopen(FileName, "r");
  7035. if (!fp) {
  7036. ExitErrMsg(TRUE, "ExST: fopen(%s) failed\n", FileName);
  7037. }
  7038. if (fseek(fp, 0, SEEK_SET)) {
  7039. ExitErrMsg(TRUE, "ExST: fseek to 0 failed\n");
  7040. }
  7041. if (!fgets(Line, sizeof(Line) - 1, fp)) {
  7042. if (ferror(fp)) {
  7043. ExitErrMsg(FALSE, "ExST: Failed to get Defs from %s\n", FileName);
  7044. } else if (feof(fp)) {
  7045. ExitErrMsg(FALSE, "ExST: Premature EOF %s\n", FileName);
  7046. }
  7047. }
  7048. do {
  7049. // skip leading spaces
  7050. pch = Line;
  7051. while (*pch && isspace(*pch)) {
  7052. pch++;
  7053. }
  7054. if (*pch == '\0')
  7055. continue;
  7056. // Grab the function name
  7057. ApiName = pch;
  7058. while(*pch != ',' && *pch != '\0')
  7059. pch++;
  7060. len = pch - ApiName;
  7061. if (len + PrependLen + 1 > sizeof(ExportName)) {
  7062. ErrMsg("ExST: ExportName Buffer overflow\n");
  7063. }
  7064. //Copy everything over
  7065. memcpy(ExportName + PrependLen, ApiName, len);
  7066. ExportName[PrependLen + len] = '\0';
  7067. if (FindInExportsList(ExportName)) {
  7068. //
  7069. // Name is already in the Exports list. Ignore the second
  7070. // one.
  7071. //
  7072. DbgPrintf("Warning: API %s was listed more than once in the services.tab. Ignoring subsequent copies.\n", ExportName);
  7073. continue;
  7074. }
  7075. memset(&ExportDebug, 0, sizeof(ExportDebug));
  7076. ExportDebug.ExportName = ExportName;
  7077. ExportDebug.MethodNumber = 3;
  7078. ExportDebug.ApiPlatform = API_ALL;
  7079. ExportDebug.Ordinal = 0;
  7080. ExportDebug.ArgsSize = -1;
  7081. if (!AddToExportsList(&ExportDebug)) {
  7082. ExitErrMsg(FALSE, "ExST: Invalid Line %s\n", Line);
  7083. }
  7084. } while (fgets(Line, sizeof(Line) - 1, fp));
  7085. if (!feof(fp) && ferror(fp)) {
  7086. ExitErrMsg(FALSE, "ExST: File Read error: %s\n", FileName);
  7087. }
  7088. fclose(fp);
  7089. return;
  7090. }
  7091. /*
  7092. * ExtractXpt-
  7093. *
  7094. * reads the exports from a ".xpt" file and builds the exports list.
  7095. * An ".xpt" file is simply a list of all of the exports.
  7096. *
  7097. */
  7098. BOOL ExtractXpt(char *XptListName, char *DllName)
  7099. {
  7100. FILE *fp=NULL;
  7101. BOOL bRet = FALSE;
  7102. char *pch;
  7103. char *pSrc=NULL;
  7104. EXPORTSDEBUG ExportDebug;
  7105. ULONG MethodNumber = 3;
  7106. char Line[MAX_PATH];
  7107. char ExportName[MAX_PATH];
  7108. char ApiName[MAX_PATH];
  7109. char Platform[MAX_PATH];
  7110. BYTE ApiPlatform;
  7111. size_t len;
  7112. DbgPrintf("ExXpt: %s\n", XptListName);
  7113. fp = fopen(XptListName, "r");
  7114. if (!fp) {
  7115. ErrMsg("ExXpt: fopen(%s) failed\n", XptListName);
  7116. goto ExSrcExit;
  7117. }
  7118. if (fseek(fp, 0, SEEK_SET)) {
  7119. ErrMsg("ExXpt: fseek failed.\n");
  7120. goto ExSrcExit;
  7121. }
  7122. if (!fgets(Line, sizeof(Line) - 1, fp)) {
  7123. if (ferror(fp)) {
  7124. ErrMsg("ExXpt: Failed to get Defs from %s\n", XptListName);
  7125. goto ExSrcExit;
  7126. } else if (feof(fp)) {
  7127. ErrMsg("ExXpt: Premature EOF %s\n", XptListName);
  7128. goto ExSrcExit;
  7129. }
  7130. }
  7131. do {
  7132. // skip leading spaces
  7133. pSrc = Line;
  7134. while (*pSrc && isspace(*pSrc)) {
  7135. pSrc++;
  7136. }
  7137. if (!*pSrc) {
  7138. // line was blank. Reset OLE method stuff for start of new
  7139. // interface then get the next line.
  7140. MethodNumber = 3;
  7141. continue;
  7142. }
  7143. if (*pSrc == ';') {
  7144. // line starts with comment. If the comment indicates the
  7145. // ole method number, grab that, then ignore the rest of the line.
  7146. pSrc++;
  7147. if (*pSrc++ == '*') {
  7148. MethodNumber = atoi(pSrc);
  7149. }
  7150. continue;
  7151. }
  7152. // Grab the exported function name
  7153. len = CopyToken(ApiName, pSrc, sizeof(ApiName)-1);
  7154. if (len >= sizeof(ApiName) -1) {
  7155. ErrMsg("ExXpt: ExportName Buffer overflow\n");
  7156. }
  7157. pSrc += len;
  7158. if (FindInExportsList(ApiName)) {
  7159. //
  7160. // Name is already in the Exports list. Ignore the second
  7161. // one.
  7162. //
  7163. DbgPrintf("Warning: API %s was listed more than once in the .xpt. Ignoring subsequent copies.\n", ApiName);
  7164. continue;
  7165. }
  7166. // skip over any whitespace after the export name
  7167. while (*pSrc && isspace(*pSrc)) {
  7168. pSrc++;
  7169. }
  7170. if (*pSrc == '\0' || *pSrc == ';') {
  7171. // nothing else interresting on the line. This API is supported
  7172. // on all platoforms.
  7173. ApiPlatform = API_ALL;
  7174. } else {
  7175. // next non-whitespace is not a comment. This API has an explicit
  7176. // list of supported platforms.
  7177. ApiPlatform = API_NONE;
  7178. do {
  7179. len = CopyToken(Platform, pSrc, sizeof(Platform)-1);
  7180. if (_stricmp(Platform, "win95") == 0) {
  7181. ApiPlatform |= API_WIN95;
  7182. } else if (_stricmp(Platform, "win98") == 0) {
  7183. ApiPlatform |= API_WIN98;
  7184. } else if (_stricmp(Platform, "nt4") == 0) {
  7185. ApiPlatform |= API_NT4;
  7186. } else if (_stricmp(Platform, "nt5") == 0) {
  7187. ApiPlatform |= API_NT5;
  7188. } else if (_stricmp(Platform, "ntx") == 0) {
  7189. ApiPlatform |= API_NTx;
  7190. } else if (_stricmp(Platform, "win9x") == 0) {
  7191. ApiPlatform |= API_WIN9x;
  7192. } else {
  7193. ExitErrMsg(FALSE, "Error: %s(%d) Unknown platform name '%s'.\n", TemplateFileName, TemplateLine, Platform);
  7194. }
  7195. pSrc += len;
  7196. while (*pSrc && isspace(*pSrc)) {
  7197. pSrc++;
  7198. }
  7199. } while (*pSrc && *pSrc != ';');
  7200. DbgPrintf("API %s has Platform %x\n", ExportName, ApiPlatform);
  7201. }
  7202. memset(&ExportDebug, 0, sizeof(ExportDebug));
  7203. ExportDebug.ExportName = ExportName;
  7204. ExportDebug.MethodNumber = MethodNumber++;
  7205. ExportDebug.ApiPlatform = ApiPlatform;
  7206. //
  7207. // Look up the export in the implib
  7208. //
  7209. if (ImplibMappedBase) {
  7210. int Len;
  7211. ULONG SymbolMember=0;
  7212. ULONG ImpNumSymbols = ImplibNumSymbols;
  7213. PULONG ImpSymbolMember = ImplibSymbolMembers;
  7214. PCHAR ImpSymbolName = ImplibSymbolNames;
  7215. while (ImpNumSymbols--) {
  7216. Len = strlen(ApiName);
  7217. pch = ImpSymbolName + 1 + Len;
  7218. if (!strncmp(ApiName, ImpSymbolName + 1, Len) &&
  7219. (!*pch || *pch == '@')) {
  7220. SymbolMember = EndianSwitch(ImpSymbolMember);
  7221. break;
  7222. }
  7223. ImpSymbolMember++;
  7224. ImpSymbolName += strlen(ImpSymbolName) + 1;
  7225. }
  7226. if (SymbolMember) {
  7227. if (!InitExportDebug(&ExportDebug, ImpSymbolName, SymbolMember)) {
  7228. goto ExSrcExit;
  7229. }
  7230. } else {
  7231. //
  7232. // The export was not found in the implib, and for
  7233. // flexibility we don't required it to be in implib.
  7234. // fill up what we know.
  7235. //
  7236. ExportDebug.Ordinal = 0;
  7237. ExportDebug.ArgsSize = -1;
  7238. strcpy(ExportName, ApiName);
  7239. }
  7240. } else {
  7241. // most info is unknown!
  7242. ExportDebug.Ordinal = 0;
  7243. ExportDebug.ArgsSize = -1;
  7244. strcpy(ExportName, ApiName);
  7245. }
  7246. if (!AddToExportsList(&ExportDebug)) {
  7247. goto ExSrcExit;
  7248. }
  7249. } while (fgets(Line, sizeof(Line) - 1, fp));
  7250. if (!feof(fp) && ferror(fp)) {
  7251. ErrMsg("ExXpt: File Read error: %s\n", XptListName);
  7252. goto ExSrcExit;
  7253. }
  7254. bRet = TRUE;
  7255. ExSrcExit:
  7256. if (!bRet) {
  7257. ErrMsg("ExXpt: Invalid Line <%s>\n%s\n", pSrc, Line);
  7258. }
  7259. if (fp) {
  7260. fclose(fp);
  7261. }
  7262. return bRet;
  7263. }
  7264. BOOL AddToExportsList(PEXPORTSDEBUG pExportsDebug)
  7265. {
  7266. PEXPORTSDEBUG pexdbg;
  7267. int Len;
  7268. int SizeExportName;
  7269. SizeExportName = strlen(pExportsDebug->ExportName) + 1;
  7270. Len = sizeof(EXPORTSDEBUG) + SizeExportName + 1;
  7271. pexdbg = GenHeapAlloc(Len);
  7272. if (!pexdbg) {
  7273. ExitErrMsg(TRUE, "GenHeapAlloc(EXPORTSDEBUG)");
  7274. }
  7275. memset(pexdbg, 0, Len);
  7276. *pexdbg = *pExportsDebug;
  7277. pexdbg->ExportName = pexdbg->Buffer;
  7278. strcpy(pexdbg->ExportName, pExportsDebug->ExportName);
  7279. InitializeListHead(&pexdbg->ArgsListHead);
  7280. InsertTailList(&ExportsList, &pexdbg->ExportsDbgEntry);
  7281. return TRUE;
  7282. }
  7283. /*
  7284. * ExtractPpm. The on-disk .PPM file is opened as read-only, but
  7285. * the pages are copy-on-write to the pagefile, so genthnk
  7286. * can make changes to the in-memory version which go away
  7287. * when it exits.
  7288. *
  7289. */
  7290. BOOL ExtractPpm(char *PpmName)
  7291. {
  7292. HANDLE hFile;
  7293. HANDLE hMapFile = NULL;
  7294. PVOID pvBaseAddress;
  7295. ULONG Version;
  7296. PVOID MappedBase;
  7297. ULONG BytesRead;
  7298. BOOL bSuccess;
  7299. PCVMHEAPHEADER pHeader;
  7300. DbgPrintf("PpmName: %s\n", PpmName);
  7301. hFile = CreateFile(PpmName,
  7302. GENERIC_READ,
  7303. FILE_SHARE_READ,
  7304. NULL,
  7305. OPEN_EXISTING,
  7306. 0,
  7307. NULL
  7308. );
  7309. if (hFile == INVALID_HANDLE_VALUE) {
  7310. hFile = NULL;
  7311. ErrMsg("ExtractPpm CreateFile(%s) gle %d\n", PpmName, GetLastError());
  7312. return FALSE;
  7313. }
  7314. bSuccess = ReadFile(hFile,
  7315. &Version,
  7316. sizeof(ULONG),
  7317. &BytesRead,
  7318. NULL
  7319. );
  7320. if (!bSuccess || BytesRead != sizeof(ULONG)) {
  7321. ErrMsg("ExtractPpm ReadFile(%s) gle %d\n", PpmName, GetLastError());
  7322. return FALSE;
  7323. }
  7324. if (Version != VM_TOOL_VERSION) {
  7325. ErrMsg("ExtractPpm: .PPM version %x does not match genthnk version %x\n",
  7326. Version, VM_TOOL_VERSION);
  7327. return FALSE;
  7328. }
  7329. #if _WIN64
  7330. // Read and ignore the 4-byte padding between the Version and the Base
  7331. bSuccess = ReadFile(hFile,
  7332. &Version,
  7333. sizeof(ULONG),
  7334. &BytesRead,
  7335. NULL
  7336. );
  7337. if (!bSuccess || BytesRead != sizeof(ULONG)) {
  7338. ErrMsg("ExtractPpm ReadFile(%s) gle %d\n", PpmName, GetLastError());
  7339. return FALSE;
  7340. }
  7341. #endif
  7342. bSuccess = ReadFile(hFile,
  7343. &pvBaseAddress,
  7344. sizeof(ULONG_PTR),
  7345. &BytesRead,
  7346. NULL
  7347. );
  7348. if (!bSuccess || BytesRead != sizeof(ULONG_PTR)) {
  7349. ErrMsg("ExtractPpm ReadFile(%s) gle %d\n", PpmName, GetLastError());
  7350. return FALSE;
  7351. }
  7352. hMapFile = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0,NULL);
  7353. if (!hMapFile) {
  7354. ErrMsg("ExtractPpm CreateFileMapping(%s) gle %d\n", PpmName, GetLastError());
  7355. return FALSE;
  7356. }
  7357. MappedBase = MapViewOfFileEx(hMapFile, FILE_MAP_COPY, 0, 0, 0, pvBaseAddress);
  7358. if (!MappedBase || MappedBase != pvBaseAddress) {
  7359. ErrMsg("ExtractPpm MapViewOfFile(%s) gle %d\n", PpmName, GetLastError());
  7360. return FALSE;
  7361. }
  7362. pHeader = (PCVMHEAPHEADER)pvBaseAddress;
  7363. FuncsList = &pHeader->FuncsList;
  7364. StructsList = &pHeader->StructsList;
  7365. TypeDefsList = &pHeader->TypeDefsList;
  7366. NIL = &pHeader->NIL;
  7367. // This must be done after NIL is initialized.
  7368. RBInitTree(&FakeFuncsList);
  7369. return TRUE;
  7370. }
  7371. void
  7372. HandlePreprocessorDirective(
  7373. char *p
  7374. )
  7375. {
  7376. ExitErrMsg(FALSE, "Preprocessor directives not allowed: '%s'\n", p);
  7377. }
  7378. char *
  7379. LexMacroArgs(
  7380. char *pch
  7381. )
  7382. {
  7383. BOOL fLexDone;
  7384. char *pchNew;
  7385. ResetLexer();
  7386. pchNew = LexOneLine(pch, FALSE, &fLexDone);
  7387. CurrentTokenIndex = 0;
  7388. if (fLexDone) {
  7389. return pchNew;
  7390. } else {
  7391. return pch;
  7392. }
  7393. }
  7394. BOOLEAN
  7395. ExpandMacro(
  7396. char *MacroName,
  7397. PCGENSTATE pCGenState,
  7398. char **ppIn,
  7399. char *OutBuffer,
  7400. SIZE_T MaxLen,
  7401. SIZE_T *BytesReturned
  7402. )
  7403. /*++
  7404. Routine Description:
  7405. Expands an @MacroName(arg1, arg2, ...).
  7406. Arguments:
  7407. MacroName - name of macro to expand
  7408. pCGenState - current code-gen state
  7409. ppIn - pointer to pointer to character following '@MacroName'
  7410. Return Value:
  7411. TRUE if macro expanded OK, FALSE if not. *ppIn will be updated to
  7412. point to the character following the end of the macro.
  7413. --*/
  7414. {
  7415. PTEMPLES pMacroTemple = 0;
  7416. PLIST_ENTRY NextMacro;
  7417. char *pIn;
  7418. PMACROARGSLIST NewMacroArgsList;
  7419. int ArgCount;
  7420. NextMacro = MacroList.Flink;
  7421. while (NextMacro != &MacroList) {
  7422. pMacroTemple = CONTAINING_RECORD(NextMacro, TEMPLES, TempleEntry);
  7423. if (strcmp(MacroName, pMacroTemple->Name) == 0) {
  7424. //
  7425. // Found a macro by that name
  7426. //
  7427. break;
  7428. }
  7429. NextMacro = NextMacro->Flink;
  7430. }
  7431. if (NextMacro == &MacroList) {
  7432. //
  7433. // No macro by that name.
  7434. //
  7435. return FALSE;
  7436. }
  7437. pIn = *ppIn;
  7438. ArgCount = pMacroTemple->IndLevel;
  7439. NewMacroArgsList = GenHeapAlloc(sizeof(MACROARGSLIST) + sizeof(LPSTR) * ArgCount);
  7440. if (!NewMacroArgsList) {
  7441. ExitErrMsg(TRUE, "ExpandMacro out of memory");
  7442. }
  7443. NewMacroArgsList->NumArgs = ArgCount;
  7444. if (!ArgCount) {
  7445. //
  7446. // This macro doesn't expect arguments
  7447. //
  7448. } else {
  7449. //
  7450. //
  7451. // This macro expects arguments. Parse the arguments.
  7452. //
  7453. pIn = ParseMacroArgs(pIn, 0, &NewMacroArgsList);
  7454. if (NewMacroArgsList->NumArgs != ArgCount) {
  7455. ExitErrMsg(FALSE, "Macro %s expects %d arguments\n", MacroName, ArgCount);
  7456. }
  7457. }
  7458. // swap out the currently active macro (if any) and swap in the new macro
  7459. MacroStack[MacroStackTop++] = pCGenState->pMacroArgsList;
  7460. pCGenState->pMacroArgsList = NewMacroArgsList;
  7461. // generate code for the Begin=/End= section of the macro
  7462. if (!pMacroTemple->CodeBurst[BeginCBI]) {
  7463. ExitErrMsg(FALSE, "%s(%d) Macro %s has no Begin= section: %s\n", TemplateFileName, TemplateLine, MacroName, *ppIn);
  7464. }
  7465. CGenerateEx(pMacroTemple->CodeBurst[BeginCBI], pCGenState, OutBuffer, MaxLen, BytesReturned);
  7466. // swap the previously active macro back in
  7467. pCGenState->pMacroArgsList = MacroStack[--MacroStackTop];
  7468. FreeMacroArgsList(NewMacroArgsList);
  7469. *ppIn = pIn;
  7470. return TRUE;
  7471. }
  7472. void
  7473. WriteBoolean (
  7474. char *pSrc,
  7475. BOOL Value
  7476. )
  7477. {
  7478. if (pSrc){
  7479. if ( Value ){
  7480. *pSrc++ = '1';
  7481. }
  7482. else{
  7483. *pSrc++ = '0';
  7484. }
  7485. *pSrc = '\0';
  7486. }
  7487. }
  7488. char *
  7489. ExtractBoolean (
  7490. char *expression,
  7491. BOOLEAN *result
  7492. )
  7493. {
  7494. char thischar = 0;
  7495. expression = SkipLeadingWhitespace(expression);
  7496. *result = FALSE;
  7497. thischar = *expression;
  7498. if ( thischar != '\0') {
  7499. char nextchar =*(expression+1);
  7500. if ( nextchar != '\0' && nextchar != ')' && nextchar != ',' && !IsWhitespaceCharacter(nextchar)) {
  7501. ExitErrMsg(FALSE,"%s(%d): Invalid Expression \"%s\"", __FILE__, __LINE__, expression);
  7502. return expression;
  7503. }
  7504. }
  7505. if (thischar == '0') {
  7506. *result = FALSE;
  7507. return expression+1;
  7508. }
  7509. else if (thischar == '1') {
  7510. *result = TRUE;
  7511. return expression+1;
  7512. }
  7513. else{
  7514. ExitErrMsg(FALSE,"%s(%d): Invalid Expression \"%s\"", __FILE__, __LINE__, expression);
  7515. return expression;
  7516. }
  7517. }
  7518. char *
  7519. ExtractBoolean1(
  7520. char *pSrc,
  7521. PCGENSTATE pCGenState,
  7522. BOOLEAN *result
  7523. )
  7524. /*++
  7525. Routine Description:
  7526. Arguments:
  7527. Return Value:
  7528. --*/
  7529. {
  7530. char *pExpression;
  7531. char *pch;
  7532. char Buffer[MAX_PATH];
  7533. SIZE_T BytesReturned;
  7534. *result = FALSE;
  7535. pch = SkipSubExpression(pSrc, &pExpression);
  7536. if (pSrc == pch) {
  7537. return pSrc;
  7538. }
  7539. pSrc = pch;
  7540. if (pExpression) {
  7541. CGenerateEx(pExpression, pCGenState, Buffer, MAX_PATH, &BytesReturned);
  7542. ExtractBoolean ( Buffer, result );
  7543. GenHeapFree(pExpression);
  7544. }
  7545. return pSrc;
  7546. }
  7547. char *
  7548. ExtractBoolean2(
  7549. char *pSrc,
  7550. PCGENSTATE pCGenState,
  7551. BOOLEAN *result1,
  7552. BOOLEAN *result2
  7553. )
  7554. /*++
  7555. Routine Description:
  7556. Arguments:
  7557. Return Value:
  7558. --*/
  7559. {
  7560. char *pExpression;
  7561. char *pch;
  7562. char Buffer[MAX_PATH];
  7563. SIZE_T BytesReturned;
  7564. *result1 = FALSE;
  7565. *result2 = FALSE;
  7566. pch = SkipSubExpression(pSrc, &pExpression);
  7567. if (pSrc == pch) {
  7568. return pSrc;
  7569. }
  7570. pSrc = pch;
  7571. if (pExpression) {
  7572. CGenerateEx(pExpression, pCGenState, Buffer, MAX_PATH, &BytesReturned);
  7573. pch = Buffer;
  7574. pch = ExtractBoolean ( Buffer, result1 );
  7575. if ( *pch == ',') {
  7576. pch++;
  7577. }
  7578. else {
  7579. ExitErrMsg(FALSE,"%s(%d): Invalid Expression \"%s\"", __FILE__, __LINE__, Buffer);
  7580. }
  7581. ExtractBoolean ( pch, result2 );
  7582. GenHeapFree(pExpression);
  7583. }
  7584. return pSrc;
  7585. }
  7586. void RestoreTrailingWhitespaceToString(char * s, char * originalEnd)
  7587. {
  7588. *(s + strlen(s)) = ' ';
  7589. }
  7590. void StripTrailingWhitespaceFromString(char * s)
  7591. {
  7592. char * t;
  7593. char * w = 0;
  7594. if (s == NULL || *s == 0)
  7595. return;
  7596. t = s + strlen(s) - 1;
  7597. while (t != s && strchr(" \t\r\n", *t) != NULL && (w = t))
  7598. {
  7599. --t;
  7600. }
  7601. if (w)
  7602. *w = 0;
  7603. }
  7604. char * SkipLeadingWhitespace(char * s)
  7605. {
  7606. return s + strspn(s, " \t\r\n");
  7607. }
  7608. BOOL IsWhitespaceCharacter(char c)
  7609. {
  7610. return (strchr(" \t\r\n", c) != NULL);
  7611. }