Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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