PageRenderTime 61ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/c2d/idl2d.d

http://github.com/rainers/visuald
D | 3041 lines | 2653 code | 237 blank | 151 comment | 678 complexity | f180be7a2979a478fd412b67f0d89ae4 MD5 | raw file
Possible License(s): AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. // This file is part of Visual D
  2. //
  3. // Visual D integrates the D programming language into Visual Studio
  4. // Copyright (c) 2010 by Rainer Schuetze, All Rights Reserved
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt
  8. //
  9. ///////////////////////////////////////////////////////////////////////
  10. //
  11. // idl2d - convert IDL or header files to D
  12. //
  13. //
  14. //
  15. module c2d.idl2d;
  16. import c2d.tokenizer;
  17. import c2d.tokutil;
  18. import c2d.dgutil;
  19. import std.string;
  20. import std.file;
  21. import std.path;
  22. import std.stdio;
  23. import std.ascii;
  24. import std.algorithm;
  25. import std.getopt;
  26. import std.utf;
  27. import std.array;
  28. import std.windows.charset;
  29. import core.memory;
  30. version = remove_pp;
  31. version = static_if_to_version;
  32. version = vsi;
  33. version = macro2template;
  34. version = targetD2;
  35. //version = Win8;
  36. class Source
  37. {
  38. string filename;
  39. string text;
  40. TokenList tokens;
  41. }
  42. // endsWith does not work reliable and crashes on page end
  43. bool _endsWith(string s, string e)
  44. {
  45. return (s.length >= e.length && s[$-e.length .. $] == e);
  46. }
  47. alias std.string.indexOf indexOf;
  48. class idl2d
  49. {
  50. ///////////////////////////////////////////////////////
  51. // configuration
  52. version(Win8)
  53. {
  54. string vsi_base_path = r"c:\l\vs9SDK"; // r"c:\l\vs9SDK";
  55. string dte_path = r"m:\s\d\visuald\trunk\sdk\vsi\idl\";
  56. string win_path = r"c:\l\vs11\Windows Kits\8.0\Include\";
  57. string sdk_d_path = r"m:\s\d\visuald\trunk\sdk\";
  58. }
  59. else version(all)
  60. {
  61. string vsi_base_path;
  62. string dte_path;
  63. string win_path;
  64. string sdk_d_path;
  65. }
  66. else version(all)
  67. {
  68. string vsi_base_path = r"c:\l\vs9SDK";
  69. string dte_path = r"m:\s\d\visuald\trunk\sdk\vsi\idl\";
  70. string win_path = r"c:\Programme\Microsoft SDKs\Windows\v6.0A\Include\";
  71. string sdk_d_path = r"m:\s\d\visuald\trunk\sdk\";
  72. }
  73. else
  74. {
  75. string vsi_base_path = r"c:\Program Files\Microsoft Visual Studio 2010 SDK"; // r"c:\l\vs9SDK";
  76. string dte_path = r"c:\s\d\visuald\trunk\sdk\vsi\idl\";
  77. string win_path = r"c:\Program Files\Microsoft SDKs\Windows\v7.1\Include\";
  78. string sdk_d_path = r"c:\s\d\visuald\trunk\sdk\";
  79. }
  80. static const string dirVSI = "vsi";
  81. static const string dirWin = "win32";
  82. string packageVSI = "sdk." ~ dirVSI ~ ".";
  83. string packageWin = "sdk." ~ dirWin ~ ".";
  84. string packageNF = "sdk.port.";
  85. string keywordPrefix = "sdk_";
  86. string vsi_path; // = vsi_base_path ~ r"\VisualStudioIntegration\Common\IDL\";
  87. string vsi_hpath; // = vsi_base_path ~ r"\VisualStudioIntegration\Common\Inc\";
  88. string vsi_d_path; // = sdk_d_path ~ r"vsi\";
  89. string win_d_path; // = sdk_d_path ~ r"win32\";
  90. string[] win_idl_files;
  91. string[] vsi_idl_files;
  92. string[] vsi_h_files;
  93. string[] dte_idl_files;
  94. version(vsi) bool vsi = true;
  95. else bool vsi = false;
  96. void initFiles()
  97. {
  98. win_idl_files = [ "windef.h", "sdkddkver.h", "basetsd.h", "ntstatus.h",
  99. "winnt.h", "winbase.h", "winuser.h", "ktmtypes.h",
  100. "winerror.h", "winreg.h", "reason.h", "commctrl.h",
  101. "wingdi.h", "prsht.h",
  102. "iphlpapi.h", "iprtrmib.h", "ipexport.h", "iptypes.h", "tcpestats.h",
  103. /*"inaddr.h", "in6addr.h",*/
  104. "ipifcons.h", "ipmib.h", "tcpmib.h", "udpmib.h",
  105. "ifmib.h", "ifdef.h", "nldef.h", "winnls.h",
  106. "shellapi.h", "rpcdce.h" /*, "rpcdcep.h"*/ ];
  107. win_idl_files ~= [ "unknwn.idl", "oaidl.idl", "wtypes.idl", "oleidl.idl",
  108. "ocidl.idl", "objidl.idl", "docobj.idl", "oleauto.h", "objbase.h",
  109. "mshtmcid.h", "xmldom.idl", "xmldso.idl", "xmldomdid.h", "xmldsodid.h", "idispids.h",
  110. "activdbg.id*", "activscp.id*", "dbgprop.id*", // only available in Windows SDK v7.x
  111. ];
  112. // only available (and are required for successfull compilation) in Windows SDK v8
  113. foreach(f; [ "wtypesbase.idl",
  114. //"winapifamily.h", "apisetcconv.h", "apiset.h", // commented because it is difficult to convert this file
  115. "minwinbase.h", "processenv.h",
  116. "minwindef.h", "fileapi.h", "debugapi.h", "handleapi.h", "errhandlingapi.h",
  117. "fibersapi.h", "namedpipeapi.h", "profileapi.h", "heapapi.h", "synchapi.h",
  118. "interlockedapi.h", "processthreadsapi.h", "sysinfoapi.h", "memoryapi.h",
  119. "threadpoollegacyapiset.h", "utilapiset.h", "ioapiset.h",
  120. "threadpoolprivateapiset.h", "threadpoolapiset.h", "bemapiset.h", "wow64apiset.h",
  121. "jobapi.h", "timezoneapi.h", "datetimeapi.h", "stringapiset.h",
  122. "libloaderapi.h", "securitybaseapi.h", "namespaceapi.h", "systemtopologyapi.h", "processtopologyapi.h",
  123. "securityappcontainer.h", "realtimeapiset.h", "unknwnbase.idl", "objidlbase.idl", "combaseapi.h",
  124. // Win SDK 8.1
  125. "mprapidef.h", "lmerr.h", "lmcons.h",
  126. // Win SDK 10.0
  127. "coml2api.h", "jobapi2.h", "propidlbase.idl",
  128. // Win SDK 10.0.10586.0
  129. "enclaveapi.h",
  130. // Win SDK 10.0.14393.0
  131. "dpa_dsa.h",
  132. // Win SDK 10.0.18362.0
  133. "fileapifromapp.h",
  134. ])
  135. win_idl_files ~= f ~ "*"; // make it optional
  136. if(vsi)
  137. {
  138. vsi_idl_files = [ "shared.idh", "vsshell.idl", "*.idl", "*.idh" ];
  139. vsi_h_files = [ "completionuuids.h", "contextuuids.h", "textmgruuids.h", "vsshelluuids.h", "vsdbgcmd.h",
  140. "venusids.h", "stdidcmd.h", "vsshlids.h", "mnuhelpids.h", "WCFReferencesIds.h",
  141. "vsdebugguids.h", "VSRegKeyNames.h", "SCGuids.h", "wbids.h", "sharedids.h",
  142. "vseeguids.h", "version.h", "scc.h",
  143. "vsplatformuiuuids.*", // only in VS2010 SDK
  144. "vscookie.*", // only in later VS2017 SDK
  145. // no longer in SDK2010: "DSLToolsCmdID.h",
  146. ];
  147. dte_idl_files = [ "*.idl" ];
  148. }
  149. }
  150. // see also preDefined, isExpressionToken, convertDefine, convertText, translateToken
  151. ///////////////////////////////////////////////////////
  152. string[string] tokImports;
  153. int[string] disabled_defines;
  154. int[string] disabled_ifdef;
  155. string[string] converted_defines;
  156. bool[] pp_enable_stack;
  157. string[] elif_braces_stack;
  158. bool convert_next_cpp_quote = true;
  159. bool cpp_quote_in_comment = false;
  160. bool[string] classes;
  161. string[string] aliases;
  162. bool[string] enums;
  163. string[] currentImports;
  164. string[] addedImports;
  165. void reinsert_cpp_quote(ref TokenIterator tokIt)
  166. {
  167. TokenIterator it = tokIt;
  168. string text;
  169. while(!it.atEnd() && it.text == "cpp_quote")
  170. {
  171. assert(it[1].text == "(");
  172. assert(it[2].type == Token.String);
  173. assert(it[3].text == ")");
  174. text ~= it.pretext;
  175. text ~= strip(it[2].text[1..$-1]);
  176. it += 4;
  177. }
  178. bool endsWithBS = text.endsWith("\\") != 0;
  179. bool quote = text.indexOf("\\\n") >= 0 || endsWithBS || !convert_next_cpp_quote;
  180. if(quote)
  181. text = tokIt.pretext ~ "/+" ~ text[tokIt.pretext.length .. $] ~ "+/";
  182. convert_next_cpp_quote = !endsWithBS;
  183. TokenList tokens = scanText(text, tokIt.lineno, true);
  184. tokIt.eraseUntil(it);
  185. tokIt = insertTokenList(tokIt, tokens);
  186. }
  187. bool handle_cpp_quote(ref TokenIterator tokIt, bool inEnum)
  188. {
  189. // tokIt on "cpp_quote"
  190. TokenIterator it = tokIt;
  191. assert(it[1].text == "(");
  192. assert(it[2].type == Token.String);
  193. assert(it[3].text == ")");
  194. string text = strip(it[2].text[1..$-1]);
  195. string txt = text;
  196. bool convert = convert_next_cpp_quote;
  197. convert_next_cpp_quote = true;
  198. if(cpp_quote_in_comment || text.startsWith("/*"))
  199. {
  200. txt = replace(text, "\\\"", "\"");
  201. cpp_quote_in_comment = (text.indexOf("*/") < 0);
  202. }
  203. else if(text.startsWith("//"))
  204. txt = replace(text, "\\\"", "\"");
  205. else if(text.endsWith("\\")) // do not convert multi-line #define
  206. {
  207. convert_next_cpp_quote = false;
  208. convert = false;
  209. }
  210. else if(text.startsWith("#"))
  211. {
  212. txt = replace(txt, "\\\"", "\"");
  213. txt = convertPP(txt, tokIt.lineno, inEnum);
  214. }
  215. if(convert)
  216. {
  217. string pretext = tokIt.pretext;
  218. tokIt.erase();
  219. tokIt.erase();
  220. tokIt.erase();
  221. tokIt.erase();
  222. txt = cpp_string(txt);
  223. TokenList tokens = scanText(txt, tokIt.lineno, false);
  224. tokIt = insertTokenList(tokIt, tokens);
  225. tokIt.pretext = pretext ~ tokIt.pretext;
  226. }
  227. else
  228. tokIt.pretext ~= "// ";
  229. return convert;
  230. }
  231. void reinsertTextTokens(ref TokenIterator tokIt, string text)
  232. {
  233. string pretext;
  234. if(!tokIt.atEnd())
  235. {
  236. pretext = tokIt.pretext;
  237. tokIt.erase();
  238. }
  239. TokenList tokens = scanText(text, tokIt.lineno, false);
  240. tokIt = insertTokenList(tokIt, tokens);
  241. tokIt.pretext = pretext ~ tokIt.pretext;
  242. }
  243. bool isExpressionToken(TokenIterator tokIt, bool first)
  244. {
  245. int type = tokIt.type;
  246. switch(type)
  247. {
  248. case Token.Identifier:
  249. switch(tokIt.text)
  250. {
  251. case "_far":
  252. case "_pascal":
  253. case "_cdecl":
  254. case "void":
  255. return false;
  256. default:
  257. return !(tokIt.text in disabled_defines);
  258. }
  259. case Token.String:
  260. case Token.Number:
  261. case Token.ParenL:
  262. case Token.BracketL:
  263. case Token.BraceL:
  264. return true;
  265. case Token.ParenR:
  266. case Token.BracketR:
  267. case Token.BraceR:
  268. if(!first)
  269. return tokIt.type != Token.Identifier && tokIt.type != Token.Number && tokIt.type != Token.ParenL;
  270. return !first;
  271. case Token.Equal:
  272. case Token.Unequal:
  273. case Token.LessThan:
  274. case Token.LessEq:
  275. case Token.GreaterThan:
  276. case Token.GreaterEq:
  277. case Token.Shl:
  278. case Token.Shr:
  279. case Token.Ampersand:
  280. case Token.Assign:
  281. case Token.Dot:
  282. case Token.Div:
  283. case Token.Mod:
  284. case Token.Xor:
  285. case Token.Or:
  286. case Token.OrOr:
  287. case Token.AmpAmpersand:
  288. return !first;
  289. case Token.Plus:
  290. case Token.Minus:
  291. case Token.Asterisk:
  292. case Token.Tilde:
  293. return true; // can be unary or binary operator
  294. case Token.Colon:
  295. case Token.Question:
  296. if(vsi)
  297. goto default;
  298. return !first;
  299. case Token.Comma:
  300. return !first && !(tokIt + 1).atEnd() && tokIt[1].type != Token.EOF;
  301. case Token.Struct:
  302. // struct at beginning of a cast?
  303. if(!tokIt.atBegin() && tokIt[-1].type == Token.ParenL)
  304. return true;
  305. return false;
  306. default:
  307. return false;
  308. }
  309. }
  310. bool hasBalancedBrackets(TokenIterator start, TokenIterator end)
  311. {
  312. int[] brackets;
  313. while (start != end)
  314. {
  315. int type = start.type;
  316. switch(type)
  317. {
  318. case Token.ParenL:
  319. case Token.BracketL:
  320. case Token.BraceL:
  321. brackets ~= type;
  322. break;
  323. case Token.ParenR:
  324. if (brackets.empty || brackets[$-1] != Token.ParenL)
  325. return false;
  326. brackets = brackets[0..$-1];
  327. break;
  328. case Token.BracketR:
  329. if (brackets.empty || brackets[$-1] != Token.BracketL)
  330. return false;
  331. brackets = brackets[0..$-1];
  332. break;
  333. case Token.BraceR:
  334. if (brackets.empty || brackets[$-1] != Token.BraceL)
  335. return false;
  336. brackets = brackets[0..$-1];
  337. break;
  338. default:
  339. break;
  340. }
  341. start++;
  342. }
  343. return brackets.empty;
  344. }
  345. bool isExpression(TokenIterator start, TokenIterator end)
  346. {
  347. if(start == end || start.type == Token.EOF)
  348. return false;
  349. if(!isExpressionToken(start, true))
  350. return false;
  351. for(TokenIterator it = start + 1; it != end && !it.atEnd() && it.type != Token.EOF; ++it)
  352. if(!isExpressionToken(it, false))
  353. return false;
  354. return hasBalancedBrackets(start, end);
  355. }
  356. bool isPrimaryExpr(TokenIterator it)
  357. {
  358. if(it.atEnd())
  359. return false;
  360. if(it.text == "(" || it.type == Token.Number || it.type == Token.Identifier)
  361. return true;
  362. return false;
  363. }
  364. string getExpressionType(string ident, TokenIterator start, TokenIterator end)
  365. {
  366. while(start != end && start.text == "(" && start[1].text == "(")
  367. ++start;
  368. if(start.text == "(" && start[1].type == Token.Identifier && start[2].text == ")" && isPrimaryExpr(start + 3))
  369. return start[1].text;
  370. if(start.text == "(" && start[1].type == Token.Identifier && start[2].text == "*" && start[3].text == ")"
  371. && isPrimaryExpr(start + 4))
  372. return start[1].text ~ start[2].text;
  373. if(start.text == "(" && start[1].text == "struct" && start[2].type == Token.Identifier && start[3].text == "*" && start[4].text == ")"
  374. && isPrimaryExpr(start + 5))
  375. return start[2].text ~ start[3].text;
  376. return "int";
  377. }
  378. string getArgumentType(string ident, TokenIterator start, TokenIterator end, string rettype)
  379. {
  380. switch(ident)
  381. {
  382. case "IS_INTRESOURCE":
  383. case "MAKEINTRESOURCEA":
  384. case "MAKEINTRESOURCEW":
  385. case "MAKEINTATOM":
  386. return "int";
  387. default:
  388. return rettype;
  389. }
  390. }
  391. void collectClasses(TokenList tokens)
  392. {
  393. for(TokenIterator tokIt = tokens.begin(); tokIt != tokens.end; ++tokIt)
  394. if(tokIt.text == "class" || tokIt.text == "interface" || tokIt.text == "coclass")
  395. classes[tokIt[1].text] = true;
  396. }
  397. bool isClassIdentifier(string ident)
  398. {
  399. if(ident in classes)
  400. return true;
  401. return false;
  402. }
  403. // 1: yes, 0: undecided, -1: no
  404. int _preDefined(string cond)
  405. {
  406. switch(cond)
  407. {
  408. case "FALSE":
  409. return -2; // not defined for expression, but for #define
  410. case "_WIN64":
  411. return 4; // special cased
  412. case "0":
  413. case "MAC":
  414. case "_MAC":
  415. case "_WIN32_WCE":
  416. case "_IA64_":
  417. case "_M_AMD64":
  418. case "RC_INVOKED":
  419. case "MIDL_PASS":
  420. case "DO_NO_IMPORTS":
  421. case "_IMM_":
  422. case "NONAMELESSUNION":
  423. case "WIN16":
  424. case "INTEROPLIB":
  425. case "__INDENTSTYLE__":
  426. case "__CTC__":
  427. case "_CTC_GUIDS_":
  428. case "CTC_INVOKED":
  429. case "VS_PACKAGE_INCLUDE":
  430. case "URTBUILD":
  431. case "NOGUIDS":
  432. case "SHOW_INCLUDES":
  433. case "RGS_INVOKED":
  434. case "__RE_E_DEFINED__":
  435. case "OLE2ANSI":
  436. // for winbase
  437. case "STRICT":
  438. case "_M_CEE":
  439. case "_M_CEE_PURE":
  440. case "_DCOM_OA_REMOTING_":
  441. case "_DCOM_OC_REMOTING_":
  442. case "_SLIST_HEADER_":
  443. case "_RTL_RUN_ONCE_DEF":
  444. case "__midl":
  445. // Windows SDK 8.0
  446. case "NOAPISET":
  447. return -1;
  448. case "WINAPI":
  449. case "WINAPI_INLINE":
  450. case "APIENTRY":
  451. case "NTAPI":
  452. case "NTAPI_INLINE":
  453. case "interface":
  454. case "PtrToPtr64":
  455. case "Ptr64ToPtr":
  456. case "HandleToHandle64":
  457. case "Handle64ToHandle":
  458. return 3; // predefined for #define, but not in normal text
  459. case "TRUE":
  460. return 2; // predefined for expression, but not for #define
  461. case "1":
  462. case "__cplusplus":
  463. case "UNICODE":
  464. case "DEFINE_GUID":
  465. case "UNIX":
  466. case "_X86_":
  467. case "_M_IX86":
  468. case "MULTIPLE_WATCH_WINDOWS":
  469. case "PROXYSTUB_BUILD":
  470. case "(defined(_WIN32)||defined(_WIN64))&&!defined(OLE2ANSI)":
  471. case "defined(_INTEGRAL_MAX_BITS)&&_INTEGRAL_MAX_BITS>=64": // needed to define LONGLONG
  472. case "!defined SENTINEL_Reason": // reason.h
  473. //case "!defined(CTC_INVOKED)&&!defined(RGS_INVOKED)":
  474. //case "!defined(_DCOM_OA_REMOTING_)&&!defined(_DCOM_OC_REMOTING_)":
  475. //case "!defined(_DCOM_OA_REMOTING_)":
  476. //case "!defined(_DCOM_OC_REMOTING_)":
  477. case "_HRESULT_DEFINED":
  478. // case "_PALETTEENTRY_DEFINED":
  479. // case "_LOGPALETTE_DEFINED":
  480. case "_REFPOINTS_DEFINED":
  481. case "COMBOX_SANDBOX":
  482. // defined to avoid #define translation
  483. case "MAKE_HRESULT":
  484. case "CBPCLIPDATA":
  485. //case "FACILITY_ITF":
  486. case "PFN_TSHELL_TMP":
  487. case "V_INT_PTR":
  488. case "VT_INT_PTR":
  489. case "V_UINT_PTR":
  490. case "VT_UINT_PTR":
  491. case "PKGRESETFLAGS":
  492. case "VSLOCALREGISTRYROOTHANDLE_TO_HKEY":
  493. case "DTE":
  494. case "Project":
  495. case "ProjectItem":
  496. case "CodeModel":
  497. case "FileCodeModel":
  498. case "IDebugMachine2_V7":
  499. case "EnumMachines_V7":
  500. case "IEnumDebugMachines2_V7":
  501. case "IID_IEnumDebugMachines2_V7":
  502. // defined with both enum and #define in ipimb.h
  503. case "MIB_IPROUTE_TYPE_OTHER":
  504. case "MIB_IPROUTE_TYPE_INVALID":
  505. case "MIB_IPROUTE_TYPE_DIRECT":
  506. case "MIB_IPROUTE_TYPE_INDIRECT":
  507. case "NULL":
  508. case "VOID":
  509. case "CONST":
  510. case "CALLBACK":
  511. case "NOP_FUNCTION":
  512. case "DECLARE_HANDLE":
  513. case "STDMETHODCALLTYPE":
  514. case "STDMETHODVCALLTYPE":
  515. case "STDAPICALLTYPE":
  516. case "STDAPIVCALLTYPE":
  517. case "STDMETHODIMP":
  518. case "STDMETHODIMP_":
  519. case "STDOVERRIDEMETHODIMP":
  520. case "STDOVERRIDEMETHODIMP_":
  521. case "IFACEMETHODIMP":
  522. case "IFACEMETHODIMP_":
  523. case "STDMETHODIMPV":
  524. case "STDMETHODIMPV_":
  525. case "STDOVERRIDEMETHODIMPV":
  526. case "STDOVERRIDEMETHODIMPV_":
  527. case "IFACEMETHODIMPV":
  528. case "IFACEMETHODIMPV_":
  529. case "_WIN32_WINNT":
  530. case "GetLastError":
  531. case "MF_END": // defined twice in winuser.h, but said to be obsolete
  532. case "__int3264":
  533. return 1;
  534. case "_NO_SCRIPT_GUIDS": // used in activdbg.h, disable to avoid duplicate GUID definitions
  535. case "EnumStackFramesEx": // used in activdbg.h, but in wrong scope
  536. case "SynchronousCallIntoThread": // used in activdbg.h, but in wrong scope
  537. return 1;
  538. // winnt.h
  539. case "_WINDEF_":
  540. case "_WINBASE_":
  541. //if(vsi)
  542. // return 1;
  543. break;
  544. case "_WIN32":
  545. //if(!vsi)
  546. return 1;
  547. //break;
  548. // Windows SDK 8.0
  549. case "_CONTRACT_GEN":
  550. return -1;
  551. // Windows SDK 10.0.15063.0
  552. case "RPC_UNICODE_SUPPORTED":
  553. return 1;
  554. case "_M_HYBRID_X86_ARM64":
  555. return -1;
  556. // Windows SDK 10.0.17134.0
  557. case "IMAGE_POLICY_METADATA_NAME":
  558. return 1;
  559. // SDK 10.0.17763.0
  560. case "EN_SEARCHWEB":
  561. case "RtlGetNonVolatileToken":
  562. case "RtlFreeNonVolatileToken":
  563. case "RtlFlushNonVolatileMemory":
  564. case "RtlDrainNonVolatileFlush":
  565. case "RtlWriteNonVolatileMemory":
  566. case "RtlFlushNonVolatileMemoryRanges":
  567. return 1;
  568. default:
  569. break;
  570. }
  571. // header double include protection
  572. if(_endsWith(cond, "_DEFINED") ||
  573. _endsWith(cond, "_INCLUDED") ||
  574. _endsWith(cond, "_h__") ||
  575. _endsWith(cond, "_H__") ||
  576. _endsWith(cond, "_H_") ||
  577. startsWith(cond, "_INC_") ||
  578. _endsWith(cond, "_IDH"))
  579. return -1;
  580. if(cond == "_" ~ toUpper(currentModule) ~ "_")
  581. return -1;
  582. if(startsWith(cond, "WINAPI_FAMILY_PARTITION"))
  583. return 1;
  584. if(indexOf(cond, "(") < 0 && indexOf(cond, "|") < 0 && indexOf(cond, "&") < 0)
  585. {
  586. if (startsWith(cond, "CMD_ZOOM_"))
  587. return 1;
  588. cond = cond.replace(" ", "");
  589. if(startsWith(cond, "WINVER>") || startsWith(cond, "_WIN32_WINNT>") || startsWith(cond, "NTDDI_VERSION>"))
  590. return 1;
  591. if(startsWith(cond, "WINVER<") || startsWith(cond, "_WIN32_WINNT<") || startsWith(cond, "NTDDI_VERSION<"))
  592. return -1;
  593. if(startsWith(cond, "_MSC_VER>") || startsWith(cond, "_MSC_FULL_VER>"))
  594. return -1; // disable all msc specials
  595. if(startsWith(cond, "_MSC_VER<") || startsWith(cond, "_MSC_FULL_VER<"))
  596. return 1; // disable all msc specials
  597. if(startsWith(cond, "_WIN32_IE>"))
  598. return 1; // assue newest IE
  599. if(startsWith(cond, "NO"))
  600. return -1; // used to disable parts, we want it all
  601. }
  602. return 0;
  603. }
  604. int findLogicalOp(string cond, string op)
  605. {
  606. int paren = 0;
  607. for(int i = 0; i <= cond.length - op.length; i++)
  608. {
  609. if(paren == 0 && cond[i .. i+op.length] == op)
  610. return i;
  611. if(cond[i] == '(')
  612. paren++;
  613. else if(cond[i] == ')')
  614. paren--;
  615. }
  616. return -1;
  617. }
  618. int preDefined(string cond)
  619. {
  620. int sign = 1;
  621. for( ; ; )
  622. {
  623. int rc = _preDefined(cond);
  624. if(rc != 0)
  625. return sign * rc;
  626. if(startsWith(cond, "(") && _endsWith(cond, ")") && findLogicalOp(cond[1..$], ")") == cond.length - 2)
  627. cond = cond[1..$-1];
  628. else if(startsWith(cond, "defined(") && findLogicalOp(cond[8..$], ")") == cond.length - 9)
  629. cond = cond[8..$-1];
  630. else if(startsWith(cond, "!") && indexOf(cond[1..$-1], "&") < 0 && indexOf(cond[1..$-1], "|") < 0)
  631. {
  632. cond = cond[1..$];
  633. sign = -sign;
  634. }
  635. else
  636. {
  637. int idx = findLogicalOp(cond, "||");
  638. if(idx < 0)
  639. idx = findLogicalOp(cond, "&&");
  640. if(idx >= 0)
  641. {
  642. int rc1 = preDefined(cond[0..idx]);
  643. int rc2 = preDefined(cond[idx+2..$]);
  644. if(cond[idx] == '|')
  645. return rc1 > 0 || rc2 > 0 ? 1 : rc1 < 0 && rc2 < 0 ? -1 : 0;
  646. else // '&'
  647. return rc1 > 0 && rc2 > 0 ? 1 : rc1 < 0 || rc2 < 0 ? -1 : 0;
  648. }
  649. break;
  650. }
  651. }
  652. return 0;
  653. }
  654. int preDefined(TokenIterator start, TokenIterator end)
  655. {
  656. string txt = tokenListToString(start, end, false, true);
  657. int rc = preDefined(txt);
  658. if(rc == 0 && verbose)
  659. writefln("\"" ~ txt ~ "\" not defined/undefined");
  660. return rc;
  661. }
  662. void handleCondition(TokenIterator tokIt, TokenIterator lastIt, string pp)
  663. {
  664. string elif_braces;
  665. int predef = preDefined(tokIt + 1, lastIt + 1);
  666. if(pp == "pp_ifndef")
  667. predef = -predef;
  668. if(predef < 0)
  669. {
  670. string ver = (predef == -4 ? "Win32" : "none");
  671. tokIt.text = "version(" ~ ver ~ ") /* " ~ tokIt.text;
  672. lastIt.text ~= " */ {/+";
  673. elif_braces = "+/} ";
  674. }
  675. else if(predef > 0)
  676. {
  677. string ver = (predef == 4 ? "Win64" : "all");
  678. tokIt.text = "version(" ~ ver ~ ") /* " ~ tokIt.text;
  679. lastIt.text ~= " */ {";
  680. elif_braces = "} ";
  681. }
  682. else
  683. {
  684. version(static_if_to_version)
  685. {
  686. string cond = pp;
  687. version(remove_pp)
  688. if(pp == "pp_ifndef")
  689. cond = "all";
  690. tokIt.text = "version(" ~ cond ~ ") /* " ~ tokIt.text;
  691. lastIt.text ~= " */ {";
  692. }
  693. else
  694. {
  695. tokIt.text = "static if(" ~ pp ~ "(r\"";
  696. tokIt[1].pretext = "";
  697. lastIt.text ~= "\")) {";
  698. }
  699. elif_braces = "} ";
  700. }
  701. if(pp == "pp_elif")
  702. {
  703. tokIt.text = elif_braces_stack[$-1] ~ "else " ~ tokIt.text;
  704. elif_braces_stack[$-1] = elif_braces;
  705. }
  706. else
  707. {
  708. elif_braces_stack ~= elif_braces;
  709. pp_enable_stack ~= true;
  710. }
  711. }
  712. bool inDisabledPPBranch()
  713. {
  714. foreach (string s; elif_braces_stack)
  715. if(startsWith(s, "+/"))
  716. return true;
  717. return false;
  718. }
  719. string convertPP(string text, int lineno, bool inEnum)
  720. {
  721. version(remove_pp) {} else
  722. if(inEnum)
  723. return "// " ~ text;
  724. TokenList tokens = scanText(text, lineno, false);
  725. TokenIterator tokIt = tokens.begin();
  726. TokenIterator lastIt = tokens.end() - 1;
  727. if(lastIt.type == Token.EOF)
  728. --lastIt;
  729. switch(tokIt.text)
  730. {
  731. case "#include":
  732. tokIt.text = "public import";
  733. if(tokIt[1].type == Token.String)
  734. tokIt[1].text = fixImport(tokIt[1].text) ~ ";";
  735. else if(tokIt[1].text == "<")
  736. {
  737. string inc;
  738. TokenIterator it = tokIt + 2;
  739. for( ; !it.atEnd() && it.text != ">"; it.erase())
  740. inc ~= it.pretext ~ it.text;
  741. tokIt[1].text = fixImport(inc);
  742. if(!it.atEnd())
  743. it.text = ";";
  744. }
  745. break;
  746. case "#if":
  747. handleCondition(tokIt, lastIt, "pp_if");
  748. break;
  749. case "#ifndef":
  750. handleCondition(tokIt, lastIt, "pp_ifndef");
  751. break;
  752. case "#ifdef":
  753. handleCondition(tokIt, lastIt, "pp_ifdef");
  754. break;
  755. case "#endif":
  756. if(pp_enable_stack.length == 0)
  757. throwException(tokIt.lineno, "unbalanced #endif");
  758. bool enabled = pp_enable_stack[$-1];
  759. pp_enable_stack = pp_enable_stack[0 .. $-1];
  760. if(!enabled)
  761. tokIt.pretext = "+/" ~ tokIt.pretext;
  762. version(remove_pp)
  763. tokIt.text = elif_braces_stack[$-1] ~ "\n";
  764. else
  765. tokIt.text = elif_braces_stack[$-1] ~ "// " ~ tokIt.text;
  766. elif_braces_stack = elif_braces_stack[0 .. $-1];
  767. break;
  768. case "#else":
  769. if(pp_enable_stack.length == 0)
  770. throwException(tokIt.lineno, "unbalanced #else");
  771. if(!pp_enable_stack[$-1])
  772. {
  773. tokIt.pretext = "+/" ~ tokIt.pretext;
  774. pp_enable_stack[$-1] = true;
  775. }
  776. if(elif_braces_stack[$-1].startsWith("+/"))
  777. {
  778. version(remove_pp)
  779. tokIt.text = "+/} else {\n";
  780. else
  781. tokIt.text = "+/} else { // " ~ tokIt.text;
  782. elif_braces_stack[$-1] = elif_braces_stack[$-1][2..$];
  783. }
  784. else
  785. {
  786. version(remove_pp)
  787. tokIt.text = "} else {\n";
  788. else
  789. tokIt.text = "} else { // " ~ tokIt.text;
  790. }
  791. break;
  792. case "#elif":
  793. if(pp_enable_stack.length == 0)
  794. throwException(tokIt.lineno, "unbalanced #elif");
  795. if(!pp_enable_stack[$-1])
  796. {
  797. tokIt.pretext = "+/" ~ tokIt.pretext;
  798. pp_enable_stack[$-1] = true;
  799. }
  800. handleCondition(tokIt, lastIt, "pp_elif");
  801. //tokIt[1].pretext = "";
  802. //lastIt.text ~= "\")) {";
  803. break;
  804. case "#define":
  805. convertDefine(tokIt);
  806. break;
  807. default:
  808. return "// " ~ text;
  809. }
  810. string txt = tokenListToString(tokens);
  811. return txt;
  812. }
  813. bool convertDefine(ref TokenIterator tokIt)
  814. {
  815. // tokIt on "#define"
  816. bool convert = true;
  817. bool predef = false;
  818. bool convertMacro = false;
  819. string argtype;
  820. string rettype;
  821. TokenIterator it = tokIt + 1;
  822. string ident = it.text;
  823. for( ; !it.atEnd(); ++it) {}
  824. version(none){
  825. if(indexOf(it.pretext, "\\\n") >= 0)
  826. {
  827. convert = false;
  828. it.pretext = replace(it.pretext, "\\\n", "\\\n//");
  829. }
  830. // if(indexOf(it.pretext, '\n') >= 0)
  831. // break;
  832. }
  833. TokenIterator endIt = it;
  834. if(it[-1].type == Token.EOF)
  835. --endIt;
  836. int preDefType = preDefined(ident);
  837. if(ident in disabled_defines)
  838. predef = true;
  839. else if (preDefType == 3)
  840. {
  841. predef = true;
  842. convert = false;
  843. }
  844. else if (preDefType == 1 || preDefined("_" ~ ident ~ "_DEFINED") == 1)
  845. predef = true;
  846. else if(tokIt[2].text == "(" && tokIt[2].pretext.length == 0)
  847. {
  848. convert = false;
  849. if(tokIt[3].text == ")")
  850. {
  851. convertMacro = hasBalancedBrackets(tokIt + 4, endIt);
  852. argtype = "";
  853. if(isExpression(tokIt + 4, endIt))
  854. rettype = getExpressionType(ident, tokIt + 4, endIt);
  855. else
  856. rettype = "void";
  857. }
  858. if(tokIt[3].type == Token.Identifier && tokIt[4].text == ")" && isExpression(tokIt + 5, endIt))
  859. {
  860. convertMacro = true;
  861. rettype = getExpressionType(ident, tokIt + 5, endIt);
  862. argtype = getArgumentType(ident, tokIt + 5, endIt, rettype);
  863. }
  864. }
  865. else if(ident.startsWith("CF_VS"))
  866. {
  867. convertMacro = true;
  868. rettype = "UINT";
  869. }
  870. else if(!isExpression(tokIt + 2, endIt))
  871. convert = false;
  872. else if(string* m = ident in converted_defines)
  873. if(*m != currentModule)
  874. predef = true;
  875. if((!convert && !convertMacro) || it[-1].text == "\\" || predef)
  876. {
  877. tokIt.pretext ~= "// ";
  878. convert = false;
  879. }
  880. if(convertMacro)
  881. {
  882. TokenIterator lastit = endIt;
  883. version(macro2template) tokIt.text = "auto";
  884. else tokIt.text = rettype;
  885. string ret = (rettype != "void" ? "return " : "");
  886. if(argtype.length)
  887. {
  888. version(macro2template) tokIt[3].pretext ~= "ARG)(ARG ";
  889. else tokIt[3].pretext ~= argtype ~ " ";
  890. tokIt[5].pretext ~= "{ " ~ ret;
  891. lastit = tokIt + 5;
  892. }
  893. else if(tokIt[2].text != "(" || tokIt[2].pretext != "")
  894. {
  895. tokIt[2].pretext = "() { " ~ ret ~ tokIt[2].pretext;
  896. lastit = tokIt + 2;
  897. }
  898. else
  899. {
  900. tokIt[4].pretext = " { " ~ ret ~ tokIt[4].pretext;
  901. lastit = tokIt + 4;
  902. }
  903. if(lastit == endIt) // empty?
  904. endIt.text ~= " }";
  905. else
  906. endIt[-1].text ~= "; }";
  907. if(!inDisabledPPBranch())
  908. converted_defines[ident] = currentModule;
  909. }
  910. else if(convert)
  911. {
  912. if(it != tokIt + 1 && it != tokIt + 2 && it != tokIt + 3)
  913. {
  914. if(endIt == tokIt + 3 && tokIt[2].type == Token.Identifier &&
  915. !(tokIt[2].text in enums) && tokIt[2].text != "NULL")
  916. {
  917. if(tokIt[2].text in disabled_defines)
  918. tokIt.pretext ~= "// ";
  919. tokIt.text = "alias";
  920. tokIt[1].text = tokIt[2].text;
  921. tokIt[2].text = ident;
  922. }
  923. else
  924. {
  925. tokIt.text = "denum";
  926. (tokIt+2).insertBefore(createToken(" ", "=", Token.Assign, tokIt.lineno));
  927. if(ident.startsWith("uuid_"))
  928. {
  929. tokIt.insertAfter(createToken(" ", "GUID", Token.Identifier, tokIt.lineno));
  930. tokIt[4].pretext ~= "uuid(\"";
  931. endIt[-1].text ~= "\")";
  932. }
  933. else if(ident.startsWith("SID_S") || ident.startsWith("guid"))
  934. {
  935. tokIt.insertAfter(createToken(" ", "GUID", Token.Identifier, tokIt.lineno));
  936. }
  937. // winnt.h
  938. else if(ident.startsWith("SECURITY_") && tokIt[3].text == "{" && tokIt[15].text == "}")
  939. {
  940. tokIt.insertAfter(createToken(" ", "SID_IDENTIFIER_AUTHORITY", Token.Identifier, tokIt.lineno));
  941. tokIt[4].text = "{[";
  942. tokIt[16].text = "]}";
  943. }
  944. else if(_endsWith(ident, "_LUID") && tokIt[3].text == "{")
  945. {
  946. tokIt.insertAfter(createToken(" ", "LUID", Token.Identifier, tokIt.lineno));
  947. }
  948. }
  949. }
  950. else
  951. tokIt.pretext ~= "// ";
  952. Token tok = createToken("", ";", Token.Comma, tokIt.lineno);
  953. endIt.insertBefore(tok);
  954. if(!inDisabledPPBranch())
  955. converted_defines[ident] = currentModule;
  956. }
  957. else if (!predef)
  958. disabled_defines[ident] = 1;
  959. string repl = (convert || convertMacro ? "\n" : "\\\n//");
  960. for(it = tokIt; !it.atEnd(); ++it)
  961. if(indexOf(it.pretext, "\\\n") >= 0)
  962. it.pretext = replace(it.pretext, "\\\n", repl);
  963. tokIt = it - 1;
  964. return convert || convertMacro;
  965. }
  966. void disable_macro(ref TokenIterator tokIt)
  967. {
  968. TokenIterator it = tokIt + 1;
  969. if(it.text == "(")
  970. {
  971. if(!advanceToClosingBracket(it))
  972. return;
  973. }
  974. version(all)
  975. {
  976. tokIt.insertBefore(createToken("", "/", Token.Div, tokIt.lineno));
  977. tokIt.insertBefore(createToken("", "+", Token.Plus, tokIt.lineno));
  978. tokIt[-2].pretext = tokIt.pretext;
  979. tokIt.pretext = " ";
  980. it.insertBefore(createToken(" ", "+", Token.Plus, tokIt.lineno));
  981. it.insertBefore(createToken("", "/", Token.Div, tokIt.lineno));
  982. tokIt = it - 1;
  983. } else {
  984. tokIt.pretext ~= "/+";
  985. it[-1].text ~= "+/"; // it.pretext = "+/" ~ it.pretext;
  986. tokIt = it - 1;
  987. }
  988. }
  989. void replaceExpressionTokens(TokenList tokens)
  990. {
  991. //replaceTokenSequence(tokens, "= (", "= cast(", true);
  992. replaceTokenSequence(tokens, "$_not $_ident($_ident1)$_ident2", "$_not cast($_ident1)$_ident2", true);
  993. replaceTokenSequence(tokens, "$_not $_ident($_ident1)$_num2", "$_not cast($_ident1)$_num2", true);
  994. replaceTokenSequence(tokens, "$_not $_ident($_ident1)-$_num2", "$_not cast($_ident1)-$_num2", true);
  995. replaceTokenSequence(tokens, "$_not $_ident($_ident1)~", "$_not cast($_ident1)~", true);
  996. while(replaceTokenSequence(tokens, "$_not $_ident($_ident1)($expr)", "$_not cast($_ident1)($expr)", true) > 0) {}
  997. replaceTokenSequence(tokens, "$_not $_ident($_ident1)cast", "$_not cast($_ident1)cast", true);
  998. replaceTokenSequence(tokens, "$_not $_ident($_ident1*)$_not_semi;", "$_not cast($_ident1*)$_not_semi", true);
  999. replaceTokenSequence(tokens, "$_not $_ident(struct $_ident1*)$_not_semi;", "$_not cast(struct $_ident1*)$_not_semi", true);
  1000. replaceTokenSequence(tokens, "$_not $_ident($_ident1 $_ident2*)", "$_not cast($_ident1 $_ident2*)", true);
  1001. replaceTokenSequence(tokens, "HRESULT cast", "HRESULT", true);
  1002. replaceTokenSequence(tokens, "extern cast", "extern", true);
  1003. replaceTokenSequence(tokens, "!cast", "!", true);
  1004. replaceTokenSequence(tokens, "reinterpret_cast<$_ident>", "cast($_ident)", true);
  1005. replaceTokenSequence(tokens, "reinterpret_cast<$_ident*>", "cast($_ident*)", true);
  1006. replaceTokenSequence(tokens, "const_cast<$_ident*>", "cast($_ident*)", true);
  1007. }
  1008. string translateModuleName(string name)
  1009. {
  1010. name = toLower(name);
  1011. if(name == "version" || name == "shared" || name == "align")
  1012. return keywordPrefix ~ name;
  1013. return name;
  1014. }
  1015. string translatePackageName(string fname)
  1016. {
  1017. // "shared", "um" added in SDK 8.0, "um\minwin" in 10.0.10586.0
  1018. return fname.replace("\\shared\\", "\\").replace("\\um\\", "\\").replace("\\minwin\\", "\\");
  1019. }
  1020. string translateFilename(string fname)
  1021. {
  1022. string name = getNameWithoutExt(fname);
  1023. string nname = translateModuleName(name);
  1024. if(name == nname)
  1025. return translatePackageName(fname);
  1026. string dir = dirName(fname);
  1027. if(dir == ".")
  1028. dir = "";
  1029. else
  1030. dir ~= "\\";
  1031. string ext = extension(fname);
  1032. return translatePackageName(dir ~ nname ~ ext);
  1033. }
  1034. string _fixImport(string text)
  1035. {
  1036. text = replace(text, "/", "\\");
  1037. text = replace(text, "\"", "");
  1038. text = toLower(getNameWithoutExt(text));
  1039. string ntext = translateFilename(text);
  1040. string name = translateModuleName(text);
  1041. foreach(string file; srcfiles)
  1042. {
  1043. if(translateModuleName(getNameWithoutExt(file)) == name)
  1044. {
  1045. if(file.startsWith(win_path))
  1046. return packageWin ~ ntext;
  1047. else
  1048. return packageVSI ~ ntext;
  1049. }
  1050. }
  1051. return packageNF ~ ntext;
  1052. }
  1053. string fixImport(string text)
  1054. {
  1055. string imp = _fixImport(text);
  1056. currentImports.addunique(imp);
  1057. return imp;
  1058. }
  1059. void convertGUID(TokenIterator tokIt)
  1060. {
  1061. // tokIt after "{"
  1062. static bool numberOrIdent(Token tok)
  1063. {
  1064. return tok.type == Token.Identifier || tok.type == Token.Number;
  1065. }
  1066. static string toByteArray(string txt)
  1067. {
  1068. string ntxt;
  1069. for(int i = 0; i + 1 < txt.length; i += 2)
  1070. {
  1071. if(i > 0)
  1072. ntxt ~= ",";
  1073. ntxt ~= "0x" ~ txt[i .. i + 2];
  1074. }
  1075. return ntxt;
  1076. }
  1077. if (numberOrIdent(tokIt[0]) && tokIt[1].text == "-" &&
  1078. numberOrIdent(tokIt[2]) && tokIt[3].text == "-" &&
  1079. numberOrIdent(tokIt[4]) && tokIt[5].text == "-" &&
  1080. numberOrIdent(tokIt[6]) && tokIt[7].text == "-" &&
  1081. numberOrIdent(tokIt[8]) && tokIt[9].text == "}" &&
  1082. tokIt[8].text.length == 12)
  1083. {
  1084. // 00020405-0000-0000-C000-000000000046
  1085. tokIt[0].text = "0x" ~ tokIt[0].text; tokIt[1].text = ",";
  1086. tokIt[2].text = "0x" ~ tokIt[2].text; tokIt[3].text = ",";
  1087. tokIt[4].text = "0x" ~ tokIt[4].text; tokIt[5].text = ",";
  1088. tokIt[6].text = "[ " ~ toByteArray(tokIt[6].text); tokIt[7].text = ",";
  1089. tokIt[8].text = toByteArray(tokIt[8].text) ~ " ]";
  1090. }
  1091. else if (tokIt[0].type == Token.Identifier && tokIt[1].text == "}")
  1092. {
  1093. // simple identifer defined elsewhere
  1094. tokIt[-1].text = "";
  1095. tokIt[1].text = "";
  1096. }
  1097. else if (tokIt[0].type == Token.Number && tokIt[1].text == "," &&
  1098. tokIt[2].type == Token.Number && tokIt[3].text == "," &&
  1099. tokIt[4].type == Token.Number && tokIt[5].text == ",")
  1100. {
  1101. // 0x0c539790, 0x12e4, 0x11cf, 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8
  1102. if(tokIt[6].text == "{")
  1103. {
  1104. tokIt[6].pretext ~= "["; // use pretext to avoid later substitution
  1105. tokIt[6].text = "";
  1106. tokIt[22].pretext ~= "]";
  1107. tokIt[22].text = "";
  1108. }
  1109. else if(tokIt[6].text != "[")
  1110. {
  1111. int i;
  1112. for(i = 0; i < 8; i++)
  1113. if(tokIt[5 + 2*i].text != "," || tokIt[6 + 2*i].type != Token.Number)
  1114. break;
  1115. if (i >= 8)
  1116. {
  1117. tokIt[6].pretext = " [" ~ tokIt[6].pretext;
  1118. tokIt[21].pretext = " ]" ~ tokIt[21].pretext;
  1119. }
  1120. }
  1121. }
  1122. else if(tokIt.type == Token.String)
  1123. {
  1124. string txt = tokIt.text;
  1125. // "af855397-c4dc-478b-abd4-c3dbb3759e72"
  1126. if(txt.length == 38 && txt[9] == '-' && txt[14] == '-' && txt[19] == '-' && txt[24] == '-')
  1127. {
  1128. tokIt.text = "0x" ~ txt[1..9] ~ ", 0x" ~ txt[10..14] ~ ", 0x" ~ txt[15..19] ~ ", [ "
  1129. ~ "0x" ~ txt[20..22] ~ ", 0x" ~ txt[22..24];
  1130. for(int i = 0; i < 6; i++)
  1131. tokIt.text ~= ", 0x" ~ txt[25 + 2*i .. 27 + 2*i];
  1132. tokIt.text ~= " ]";
  1133. }
  1134. }
  1135. else
  1136. {
  1137. tokIt.pretext ~= "\"";
  1138. while(tokIt.text != "}")
  1139. {
  1140. ++tokIt;
  1141. if(tokIt.atEnd())
  1142. return;
  1143. }
  1144. tokIt.pretext = "\"" ~ tokIt.pretext;
  1145. }
  1146. }
  1147. string convertText(TokenList tokens)
  1148. {
  1149. string prevtext;
  1150. int braceCount;
  1151. int parenCount;
  1152. int brackCount;
  1153. int enumLevel = -1;
  1154. //replaceTokenSequence(tokens, "enum Kind { $enums ;", "class Kind { /+ $enums; +/", false);
  1155. // do some preprocessor replacements to make the text bracket-balanced
  1156. if(currentModule == "oaidl")
  1157. {
  1158. replaceTokenSequence(tokens, "__VARIANT_NAME_1", "", true);
  1159. replaceTokenSequence(tokens, "__VARIANT_NAME_2", "", true);
  1160. replaceTokenSequence(tokens, "__VARIANT_NAME_3", "", true);
  1161. replaceTokenSequence(tokens, "__VARIANT_NAME_4", "", true);
  1162. }
  1163. if(currentModule == "windef")
  1164. {
  1165. // avoid removal of #define TRUE 1
  1166. replaceTokenSequence(tokens, "#ifndef TRUE\n#define TRUE$def\n#endif\n", "#define TRUE 1\n", false);
  1167. }
  1168. if(currentModule == "winnt")
  1169. {
  1170. replaceTokenSequence(tokens, "#if defined(MIDL_PASS)\ntypedef struct $_ident {\n"
  1171. ~ "#else$comment_else\n$else\n#endif$comment_endif", "$else", false);
  1172. // remove int64 operations
  1173. replaceTokenSequence(tokens, "#if defined(MIDL_PASS)$if_more\n#define Int32x32To64$def_more\n$defines\n"
  1174. ~ "#error Must define a target architecture.\n#endif\n", "/+\n$*\n+/", false);
  1175. // remove rotate operations
  1176. replaceTokenSequence(tokens, "#define RotateLeft8$def_more\n$defines\n"
  1177. ~ "#pragma intrinsic(_rotr16)\n", "/+\n$*\n+/", false);
  1178. replaceTokenSequence(tokens, "typedef struct DECLSPEC_ALIGN($_num)", "align($_num) typedef struct", true);
  1179. replaceTokenSequence(tokens, "typedef union DECLSPEC_ALIGN($_num)", "align($_num) typedef union", true);
  1180. replaceTokenSequence(tokens, "struct DECLSPEC_ALIGN($_num)", "align($_num) struct", true);
  1181. // win 8.1: remove template _ENUM_FLAG_INTEGER_FOR_SIZE
  1182. replaceTokenSequence(tokens, "template $args _ENUM_FLAG_INTEGER_FOR_SIZE;", "/*$0*/", true);
  1183. replaceTokenSequence(tokens, "template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE <$arg> { $def };", "/*$0*/", true);
  1184. replaceTokenSequence(tokens, "template <$arg> struct _ENUM_FLAG_SIZED_INTEGER { $def };", "/*$0*/", true);
  1185. // win 10.0.17134.0: typedef enum MEM_EXTENDED_PARAMETER_TYPE {} MEM_EXTENDED_PARAMETER_TYPE, ...
  1186. replaceTokenSequence(tokens, "MEM_EXTENDED_PARAMETER_TYPE, *PMEM_EXTENDED_PARAMETER_TYPE", "*PMEM_EXTENDED_PARAMETER_TYPE", true);
  1187. // win 10.0.17763.0: typedef enum MEM_SECTION_EXTENDED_PARAMETER_TYPE {} MEM_SECTION_EXTENDED_PARAMETER_TYPE, ...
  1188. replaceTokenSequence(tokens, "MEM_SECTION_EXTENDED_PARAMETER_TYPE, *PMEM_SECTION_EXTENDED_PARAMETER_TYPE", "*PMEM_SECTION_EXTENDED_PARAMETER_TYPE", true);
  1189. // win 10.0.18362.0: typedef struct DECLSPEC_ALIGN(16) DECLSPEC_NOINITALL _CONTEXT ...
  1190. replaceTokenSequence(tokens, "DECLSPEC_NOINITALL", "", true);
  1191. replaceTokenSequence(tokens, "RtlZeroMemory($dest,$length)",
  1192. "import core.stdc.string: memset; memset($dest,0,$length)", true);
  1193. }
  1194. if(currentModule == "commctrl")
  1195. {
  1196. // typos
  1197. replaceTokenSequence(tokens, "PCCOMBOEXITEMW", "PCCOMBOBOXEXITEMW", true);
  1198. replaceTokenSequence(tokens, "LPTBSAVEPARAMW", "LPTBSAVEPARAMSW", true);
  1199. }
  1200. if(currentModule == "oleauto")
  1201. {
  1202. replaceTokenSequence(tokens, "WINOLEAUTAPI_($_rettype)", "extern(Windows) $_rettype", true);
  1203. replaceTokenSequence(tokens, "WINOLEAUTAPI", "extern(Windows) HRESULT", true);
  1204. // rename the three argument inlined overload, LDC stumbles over it
  1205. replaceTokenSequence(tokens, "VarCmp($arg1, $arg2, $arg3) { $code$ }",
  1206. "VarCmp_inl($arg1, $arg2, $arg3) { $code$ }", true);
  1207. }
  1208. if(currentModule == "shellapi")
  1209. {
  1210. replaceTokenSequence(tokens, "SHSTDAPI_($_rettype)", "extern(Windows) $_rettype", true);
  1211. replaceTokenSequence(tokens, "SHSTDAPI", "extern(Windows) HRESULT", true);
  1212. replaceTokenSequence(tokens, "LWSTDAPIV_($_rettype)", "extern(Windows) $_rettype", true);
  1213. }
  1214. replaceTokenSequence(tokens, "STDAPI_($_rettype)", "extern(Windows) $_rettype", true);
  1215. replaceTokenSequence(tokens, "STDAPI", "extern(Windows) HRESULT", true);
  1216. replaceTokenSequence(tokens, "STDMETHODCALLTYPE", "extern(Windows)", true);
  1217. replaceTokenSequence(tokens, "STDAPICALLTYPE", "extern(Windows)", true);
  1218. replaceTokenSequence(tokens, "WINOLEAPI_($_rettype)", "extern(Windows) $_rettype", true);
  1219. replaceTokenSequence(tokens, "WINOLEAPI", "extern(Windows) HRESULT", true);
  1220. replaceTokenSequence(tokens, "$_ident WINAPIV", "extern(C) $_ident", true);
  1221. replaceTokenSequence(tokens, "RPCRTAPI", "export", true);
  1222. replaceTokenSequence(tokens, "RPC_STATUS", "int", true);
  1223. replaceTokenSequence(tokens, "RPC_ENTRY", "extern(Windows)", true);
  1224. replaceTokenSequence(tokens, "__RPC_USER", "extern(Windows)", true);
  1225. replaceTokenSequence(tokens, "__RPC_STUB", "extern(Windows)", true);
  1226. replaceTokenSequence(tokens, "__RPC_API", "extern(Windows)", true);
  1227. replaceTokenSequence(tokens, "RPC_MGR_EPV", "void", true);
  1228. replaceTokenSequence(tokens, "__RPC_FAR", "", true);
  1229. replaceTokenSequence(tokens, "POINTER_32", "", true);
  1230. replaceTokenSequence(tokens, "POINTER_64", "", true);
  1231. replaceTokenSequence(tokens, "UNREFERENCED_PARAMETER($arg);", "/*UNREFERENCED_PARAMETER($arg);*/", true);
  1232. if(currentModule == "rpcdce")
  1233. {
  1234. replaceTokenSequence(tokens, "RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN($args);",
  1235. "function($args) RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN;", true);
  1236. }
  1237. // windef.h and ktmtypes.h
  1238. replaceTokenSequence(tokens, "UOW UOW;", "UOW uow;", true);
  1239. // enc.idl (FIELD_OFFSET already defined in winnt.h)
  1240. replaceTokenSequence(tokens, "typedef struct _FIELD_OFFSET { $data } FIELD_OFFSET;",
  1241. "struct _FIELD_OFFSET { $data };", true);
  1242. // IP_DEST_PORT_UNREACHABLE defined twice
  1243. if(currentModule == "ipexport")
  1244. {
  1245. replaceTokenSequence(tokens, "#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)\n" ~
  1246. "#define IP_HOP_LIMIT_EXCEEDED (IP_STATUS_BASE + 13)\n",
  1247. "#define IP_HOP_LIMIT_EXCEEDED (IP_STATUS_BASE + 13)\n", false);
  1248. }
  1249. if(currentModule == "nldef")
  1250. {
  1251. // expand MAKE_ROUTE_PROTOCOL
  1252. replaceTokenSequence(tokens, "MAKE_ROUTE_PROTOCOL($_ident,$_num),",
  1253. "MIB_IPPROTO_ __ $_ident = $_num, PROTO_IP_ __ $_ident = $_num,", true);
  1254. }
  1255. if(currentModule == "iphlpapi")
  1256. {
  1257. // imports inside extern(C) {}
  1258. replaceTokenSequence(tokens, "extern \"C\" { $_data }", "$_data", true);
  1259. }
  1260. if(currentModule == "fileapifromapp")
  1261. {
  1262. replaceTokenSequence(tokens, "WINSTORAGEAPI", "", true);
  1263. }
  1264. if(currentModule == "propidlbase")
  1265. {
  1266. replaceTokenSequence(tokens, "_VARIANT_BOOL bool;", "/*_VARIANT_BOOL bool;*/", true);
  1267. replaceTokenSequence(tokens, "TYPEDEF_CA($_identType,$_identName);",
  1268. "struct $_identName { ULONG cElems; $_identType* pElems; };", true);
  1269. }
  1270. if(currentModule == "imageparameters140")
  1271. {
  1272. // type name and field name identical
  1273. replaceTokenSequence(tokens, "ImageMoniker ImageMoniker;", "ImageMoniker mImageMoniker;", true);
  1274. }
  1275. // select unicode version of the API when defining without postfix A/W
  1276. replaceTokenSequence(tokens, "#ifdef UNICODE\nreturn $_identW(\n#else\nreturn $_identA(\n#endif\n",
  1277. " return $_identW(", false);
  1278. replaceTokenSequence(tokens, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false);
  1279. replaceTokenSequence(tokens, "#ifdef defined(__cplusplus)\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false);
  1280. replaceTokenSequence(tokens, "#ifdef defined __cplusplus\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false);
  1281. replaceTokenSequence(tokens, "#ifdef __cplusplus\n}\n#endif\n", "}\n", false);
  1282. if(currentModule == "vsshell160")
  1283. {
  1284. replaceTokenSequence(tokens, "#ifndef INTEROPLIB\n[in] $ifcode\n#else\n$elsecode\n#endif", "[in] $ifcode", false);
  1285. }
  1286. for(TokenIterator tokIt = tokens.begin(); tokIt != tokens.end; )
  1287. {
  1288. Token tok = *tokIt;
  1289. switch(tok.text)
  1290. {
  1291. case "(":
  1292. parenCount++;
  1293. break;
  1294. case ")":
  1295. parenCount--;
  1296. break;
  1297. case "[":
  1298. brackCount++;
  1299. break;
  1300. case "]":
  1301. brackCount--;
  1302. break;
  1303. case "{":
  1304. braceCount++;
  1305. break;
  1306. case "}":
  1307. braceCount--;
  1308. if(braceCount <= enumLevel)
  1309. enumLevel = -1;
  1310. break;
  1311. case "enum":
  1312. enumLevel = braceCount;
  1313. break;
  1314. case ";":
  1315. enumLevel = -1;
  1316. break;
  1317. case "importlib":
  1318. if(tokIt[1].text == "(" && tokIt[2].type == Token.String && tokIt[3].text == ")")
  1319. {
  1320. tokIt.text = "import";
  1321. tokIt[1].text = "";
  1322. tokIt[2].pretext = " ";
  1323. tokIt[2].text = fixImport(tokIt[2].text);
  1324. tokIt[3].text = "";
  1325. }
  1326. break;
  1327. case "import":
  1328. if(tokIt[1].type == Token.String)
  1329. {
  1330. tokIt.pretext ~= "public ";
  1331. tokIt[1].text = fixImport(tokIt[1].text);
  1332. }
  1333. break;
  1334. case "midl_pragma":
  1335. comment_line(tokIt);
  1336. continue;
  1337. case "cpp_quote":
  1338. //reinsert_cpp_quote(tokIt);
  1339. if(handle_cpp_quote(tokIt, enumLevel >= 0))
  1340. continue;
  1341. break;
  1342. case "version":
  1343. case "align":
  1344. case "package":
  1345. case "function":
  1346. if(tokIt[1].text != "(")
  1347. tok.text = keywordPrefix ~ tok.text;
  1348. break;
  1349. case "unsigned":
  1350. {
  1351. string t;
  1352. bool skipNext = true;
  1353. switch(tokIt[1].text)
  1354. {
  1355. case "__int64": t = "ulong"; break;
  1356. case "long": t = "uint"; break;
  1357. case "int": t = "uint"; break;
  1358. case "__int32": t = "uint"; break;
  1359. case "__int3264": t = "uint"; break;
  1360. case "short": t = "ushort"; break;
  1361. case "char": t = "ubyte"; break;
  1362. default:
  1363. t = "uint";
  1364. skipNext = false;
  1365. break;
  1366. }
  1367. tok.text = t;
  1368. if(skipNext)
  1369. (tokIt + 1).erase();
  1370. break;
  1371. }
  1372. case "signed":
  1373. {
  1374. string t;
  1375. bool skipNext = true;
  1376. switch(tokIt[1].text)
  1377. {
  1378. case "__int64": t = "long"; break;
  1379. case "long": t = "int"; break;
  1380. case "int": t = "int"; break;
  1381. case "__int32": t = "int"; break;
  1382. case "__int3264": t = "int"; break;
  1383. case "short": t = "short"; break;
  1384. case "char": t = "byte"; break;
  1385. default:
  1386. t = "int";
  1387. skipNext = false;
  1388. break;
  1389. }
  1390. tok.text = t;
  1391. if(skipNext)
  1392. (tokIt + 1).erase();
  1393. break;
  1394. }
  1395. // Windows SDK 8.0 => 7.1
  1396. case "_Null_terminated_": tok.text = "__nullterminated"; break;
  1397. case "_NullNull_terminated_": tok.text = "__nullnullterminated"; break;
  1398. case "_Success_": tok.text = "__success"; break;
  1399. case "_In_": tok.text = "__in"; break;
  1400. case "_Inout_": tok.text = "__inout"; break;
  1401. case "_In_opt_": tok.text = "__in_opt"; break;
  1402. case "_Inout_opt_": tok.text = "__inout_opt"; break;
  1403. case "_Inout_z_": tok.text = "__inout_z"; break;
  1404. case "_Deref_out_": tok.text = "__deref_out"; break;
  1405. case "_Out_": tok.text = "__out"; break;
  1406. case "_Out_opt_": tok.text = "__out_opt"; break;
  1407. case "_Field_range_": tok.text = "__range"; break;
  1408. case "_Field_size_": tok.text = "__field_ecount"; break;
  1409. case "_Field_size_opt_": tok.text = "__field_ecount_opt"; break;
  1410. case "_Field_size_bytes_": tok.text = "__field_bcount"; break;
  1411. case "_Field_size_bytes_opt_":tok.text = "__field_bcount_opt"; break;
  1412. default:
  1413. if(tok.type == Token.Macro && tok.text.startsWith("$"))
  1414. tok.text = "_d_" ~ tok.text[1..$];
  1415. else if(tok.type == Token.Number && (tok.text._endsWith("l") || tok.text._endsWith("L")))
  1416. tok.text = tok.text[0..$-1];
  1417. else if(tok.type == Token.Number && tok.text._endsWith("i64"))
  1418. tok.text = tok.text[0..$-3] ~ "L";
  1419. else if(tok.type == Token.Number && tok.text._endsWith("UI64"))
  1420. tok.text = tok.text[0..$-4] ~ "UL";
  1421. else if(tok.type == Token.String && tok.text.startsWith("L\""))
  1422. tok.text = tok.text[1..$] ~ "w.ptr";
  1423. else if(tok.type == Token.String && tok.text.startsWith("L\'"))
  1424. tok.text = tok.text[1..$];
  1425. else if(tok.text.startsWith("#"))
  1426. {
  1427. string txt = convertPP(tok.text, tok.lineno, enumLevel >= 0);
  1428. reinsertTextTokens(tokIt, txt);
  1429. continue;
  1430. }
  1431. else if(tok.text in disabled_defines)
  1432. disable_macro(tokIt);
  1433. else if(parenCount > 0)
  1434. {
  1435. // in function argument
  1436. //if(tok.text == "const" || tok.text == "CONST")
  1437. // tok.text = "/*const*/";
  1438. //else
  1439. if (tok.text.startsWith("REF") &&
  1440. tok.text != "REFSHOWFLAGS" && !tok.text.startsWith("REFERENCE"))
  1441. {
  1442. tokIt.insertBefore(createToken(tok.pretext, "ref", Token.Identifier, tokIt.lineno));
  1443. tok.pretext = " ";
  1444. tok.text = tok.text[3..$];
  1445. }
  1446. }
  1447. else if(tok.type == Token.Identifier && enumLevel >= 0 && (tokIt[-1].text == "{" || tokIt[-1].text == ","))
  1448. enums[tok.text] = true;
  1449. break;
  1450. }
  1451. prevtext = tok.text;
  1452. ++tokIt;
  1453. }
  1454. version(none) version(vsi)
  1455. {
  1456. // wtypes.idl:
  1457. replaceTokenSequence(tokens, "typedef ubyte UCHAR;", "typedef ubyte idl_UCHAR;", true);
  1458. replaceTokenSequence(tokens, "typedef short SHORT;", "typedef short idl_SHORT;", true);
  1459. replaceTokenSequence(tokens, "typedef ushort USHORT;", "typedef ushort idl_USHORT;", true);
  1460. replaceTokenSequence(tokens, "typedef DWORD ULONG;", "typedef DWORD idl_ULONG;", true);
  1461. replaceTokenSequence(tokens, "typedef double DOUBLE;", "typedef double idl_DOUBLE;", true);
  1462. replaceTokenSequence(tokens, "typedef char OLECHAR;", "typedef char idl_OLECHAR;", true);
  1463. replaceTokenSequence(tokens, "typedef LPSTR LPOLESTR;", "typedef LPSTR idl_LPOLESTR;", true);
  1464. replaceTokenSequence(tokens, "typedef LPCSTR LPCOLESTR;", "typedef LPCSTR idl_LPCOLESTR;", true);
  1465. replaceTokenSequence(tokens, "WCHAR OLECHAR;", "WCHAR idl_OLECHAR;", true);
  1466. replaceTokenSequence(tokens, "OLECHAR *LPOLESTR;", "OLECHAR *idl_LPOLESTR;", true);
  1467. replaceTokenSequence(tokens, "const OLECHAR *LPCOLESTR;", "OLECHAR *idl_LPCOLESTR;", true);
  1468. replaceTokenSequence(tokens, "typedef LONG SCODE;", "typedef LONG vsi_SCODE;", true);
  1469. }
  1470. //replaceTokenSequence(tokens, "interface IWinTypes { $data }",
  1471. // "/+interface IWinTypes {+/\n$data\n/+ } /+IWinTypes+/ +/", true);
  1472. // docobj.idl (v6.0a)
  1473. if(currentModule == "docobj")
  1474. {
  1475. replaceTokenSequence(tokens, "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000, OLECMDIDF_REFRESH_THROUGHSCRIPT = 0x4000 $_not,",
  1476. "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000,\nOLECMDIDF_REFRESH_THROUGHSCRIPT = 0x4000, $_not", true);
  1477. r

Large files files are truncated, but you can click here to view the full file