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.

8864 lines
256 KiB

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