PageRenderTime 66ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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. replaceTokenSequence(tokens, "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000 $_not,", "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000, $_not", true);
  1478. // win SDK 8.1: double define
  1479. replaceTokenSequence(tokens, "typedef struct tagPAGESET {} PAGESET;", "", true);
  1480. }
  1481. //vsshell.idl
  1482. if(currentModule == "vsshell")
  1483. {
  1484. replaceTokenSequence(tokens, "typedef DWORD PFN_TSHELL_TMP;", "typedef PfnTshell PFN_TSHELL_TMP;", true);
  1485. replaceTokenSequence(tokens, "MENUEDITOR_TRANSACTION_ALL,", "MENUEDITOR_TRANSACTION_ALL = 0,", true);
  1486. replaceTokenSequence(tokens, "SCC_STATUS_INVALID = -1L,", "SCC_STATUS_INVALID = cast(DWORD)-1L,", true);
  1487. }
  1488. if(currentModule == "vsshell80")
  1489. {
  1490. replaceTokenSequence(tokens, "MENUEDITOR_TRANSACTION_ALL,", "MENUEDITOR_TRANSACTION_ALL = 0,", true); // overflow from -1u
  1491. }
  1492. // vslangproj90.idl
  1493. if(currentModule == "vslangproj90")
  1494. replaceTokenSequence(tokens, "CsharpProjectConfigurationProperties3", "CSharpProjectConfigurationProperties3", true);
  1495. if(currentModule == "msdbg")
  1496. replaceTokenSequence(tokens, "const DWORD S_UNKNOWN = 0x3;", "denum DWORD S_UNKNOWN = 0x3;", true);
  1497. if(currentModule == "msdbg167")
  1498. replaceTokenSequence(tokens, "__uuidof($data)", "$data.iid", true);
  1499. if(currentModule == "activdbg")
  1500. replaceTokenSequence(tokens, "const THREAD_STATE", "denum THREAD_STATE", true);
  1501. if(currentModule == "objidl")
  1502. {
  1503. replaceTokenSequence(tokens, "const OLECHAR *COLE_DEFAULT_PRINCIPAL", "denum const OLECHAR *COLE_DEFAULT_PRINCIPAL", true);
  1504. replaceTokenSequence(tokens, "const void *COLE_DEFAULT_AUTHINFO", "denum const void *COLE_DEFAULT_AUTHINFO", true);
  1505. }
  1506. if(currentModule == "combaseapi")
  1507. {
  1508. replaceTokenSequence(tokens, "typedef enum CWMO_FLAGS", "typedef enum tagCWMO_FLAGS", true);
  1509. }
  1510. if(currentModule == "lmcons")
  1511. {
  1512. replaceTokenSequence(tokens, "alias NERR_BASE MIN_LANMAN_MESSAGE_ID;", "enum MIN_LANMAN_MESSAGE_ID = 2100;", true); // missing lmerr.h
  1513. }
  1514. if(currentModule == "winnt")
  1515. {
  1516. // Win SDK 8.1: remove translation to intrinsics
  1517. replaceTokenSequence(tokens, "alias _InterlockedAnd InterlockedAnd;", "/+ $*", true);
  1518. replaceTokenSequence(tokens, "InterlockedCompareExchange($args __in LONG ExChange, __in LONG Comperand);", "$* +/", true);
  1519. replaceTokenSequence(tokens, "InterlockedOr(&Barrier, 0);", "InterlockedExchangeAdd(&Barrier, 0);", true); // InterlockedOr exist only as intrinsic
  1520. }
  1521. if(currentModule == "ocidl")
  1522. {
  1523. // move alias out of interface declaration, it causes circular definitions with dmd 2.065+
  1524. replaceTokenSequence(tokens, "interface IOleUndoManager : IUnknown { alias IID_IOleUndoManager SID_SOleUndoManager; $data }",
  1525. "interface IOleUndoManager : IUnknown { $data }\n\nalias IID_IOleUndoManager SID_SOleUndoManager;", true);
  1526. }
  1527. replaceTokenSequence(tokens, "extern const __declspec(selectany)", "dconst", true);
  1528. replaceTokenSequence(tokens, "EXTERN_C $args;", "/+EXTERN_C $args;+/", true);
  1529. replaceTokenSequence(tokens, "SAFEARRAY($args)", "SAFEARRAY/*($args)*/", true);
  1530. // remove forward declarations
  1531. replaceTokenSequence(tokens, "enum $_ident;", "/+ enum $_ident; +/", true);
  1532. replaceTokenSequence(tokens, "struct $_ident;", "/+ struct $_ident; +/", true);
  1533. replaceTokenSequence(tokens, "struct __declspec($expr) $_ident;", "/+ struct __declspec($expr) $_ident; +/", true);
  1534. replaceTokenSequence(tokens, "class $_ident;", "/+ class $_ident; +/", true);
  1535. replaceTokenSequence(tokens, "interface $_ident;", "/+ interface $_ident; +/", true);
  1536. replaceTokenSequence(tokens, "dispinterface $_ident;", "/+ dispinterface $_ident; +/", true);
  1537. replaceTokenSequence(tokens, "coclass $_ident;", "/+ coclass $_ident; +/", true);
  1538. replaceTokenSequence(tokens, "library $_ident {", "version(all)\n{ /+ library $_ident +/", true);
  1539. replaceTokenSequence(tokens, "importlib($expr);", "/+importlib($expr);+/", true);
  1540. version(remove_pp)
  1541. {
  1542. string tsttxt = tokenListToString(tokens);
  1543. while(replaceTokenSequence(tokens, "$_note else version(all) { $if } else { $else }", "$_note $if", true) > 0 ||
  1544. replaceTokenSequence(tokens, "$_note else version(all) { $if } else version($ver) { $else_ver } else { $else }", "$_note $if", true) > 0 ||
  1545. replaceTokenSequence(tokens, "$_note else version(all) { $if } $_not else", "$_note $if\n$_not", true) > 0 ||
  1546. replaceTokenSequence(tokens, "$_note else version(none) { $if } else { $else }", "$_note $else", true) > 0 ||
  1547. replaceTokenSequence(tokens, "$_note else version(none) { $if } $_not else", "$_note $_not", true) > 0 ||
  1548. replaceTokenSequence(tokens, "version(pp_if) { $if } else { $else }", "$else", true) > 0 ||
  1549. replaceTokenSequence(tokens, "version(pp_if) { $if } $_not else", "$_not", true) > 0 ||
  1550. replaceTokenSequence(tokens, "version(pp_ifndef) { $if } else { $else }", "$if", true) > 0 ||
  1551. replaceTokenSequence(tokens, "version(pp_ifndef) { $if } $_not else", "$if\n$_not", true) > 0)
  1552. {
  1553. string rtsttxt = tokenListToString(tokens);
  1554. }
  1555. string ntsttxt = tokenListToString(tokens);
  1556. }
  1557. while(replaceTokenSequence(tokens, "static if($expr) { } else { }", "", true) > 0 ||
  1558. replaceTokenSequence(tokens, "static if($expr) { } $_not else", "$_not", true) > 0 ||
  1559. replaceTokenSequence(tokens, "version($expr) { } else { }", "", true) > 0 ||
  1560. replaceTokenSequence(tokens, "version($expr) { } $_not else", "$_not", true) > 0) {}
  1561. // move declaration at the top of the interface below the interface while keeping the order
  1562. replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data }",
  1563. "interface $_ident1 : $_identbase { $data\n} __eo_interface", true);
  1564. while(replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { typedef $args; $data } $tail __eo_interface",
  1565. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ntypedef $args; __eo_interface", true) > 0
  1566. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { denum $args; $data } $tail __eo_interface",
  1567. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndenum $args; __eo_interface", true) > 0
  1568. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { enum $args; $data } $tail __eo_interface",
  1569. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nenum $args; __eo_interface", true) > 0
  1570. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { dconst $_ident = $expr; $data } $tail __eo_interface",
  1571. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndconst $_ident = $expr; __eo_interface", true) > 0
  1572. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype $_ident = $expr; $data } $tail __eo_interface",
  1573. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype $_ident = $expr; __eo_interface", true) > 0
  1574. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype *$_ident = $expr; $data } $tail __eo_interface",
  1575. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype *$_ident = $expr; __eo_interface", true) > 0
  1576. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { struct $args; $data } $tail __eo_interface",
  1577. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstruct $args; __eo_interface", true) > 0
  1578. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { union $args; $data } $tail __eo_interface",
  1579. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nunion $args; __eo_interface", true) > 0
  1580. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { static if($expr) { $if } else { $else } $data } $tail __eo_interface",
  1581. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstatic if($expr) {\n$if\n} else {\n$else\n} __eo_interface", true) > 0
  1582. || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { version($expr) {/+ typedef $if } else { $else } $data } $tail __eo_interface",
  1583. "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nversion($expr) {/+\ntypedef $if\n} else {\n$else\n} __eo_interface", true) > 0
  1584. ) {}
  1585. replaceTokenSequence(tokens, "__eo_interface", "", true);
  1586. replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data const DISPID $constids }",
  1587. "interface $_ident1 : $_identbase { $data\n}\n\nconst DISPID $constids\n", true);
  1588. version(none)
  1589. {
  1590. replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident2;",
  1591. "enum $_ident2\n{\n$enums\n}", true);
  1592. replaceTokenSequence(tokens, "typedef enum { $enums } $_ident2;",
  1593. "enum $_ident2\n{\n$enums\n}", true);
  1594. replaceTokenSequence(tokens, "typedef [$_ident3] enum $_ident1 { $enums } $_ident2;",
  1595. "enum $_ident2\n{\n$enums\n}", true);
  1596. replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;",
  1597. "enum $_ident2 : $_identbase\n{\n$enums\n}", true);
  1598. } else {
  1599. replaceTokenSequence(tokens, "typedef enum $_ident1 : uint { $enums } $_ident1;",
  1600. "enum $_ident1 : uint\n{\n$enums\n}\n", true);
  1601. replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident1;",
  1602. "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true);
  1603. replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $ident2;",
  1604. "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true);
  1605. replaceTokenSequence(tokens, "typedef enum { $enums } $ident2;",
  1606. "enum\n{\n$enums\n}\ntypedef int $ident2;", true);
  1607. replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $_ident1;",
  1608. "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true);
  1609. replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $ident2;",
  1610. "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true);
  1611. replaceTokenSequence(tokens, "typedef [$info] enum { $enums } $ident2;",
  1612. "enum [$info]\n{\n$enums\n}\ntypedef int $ident2;", true);
  1613. replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;",
  1614. "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef $_identbase $_ident1;\ntypedef $_identbase $_ident2;", true);
  1615. replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef [$info] $_identbase $_ident2;",
  1616. "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef [$info] $_identbase $_ident2;", true);
  1617. replaceTokenSequence(tokens, "enum $_ident1 { $enums };",
  1618. "enum /+$_ident1+/ : int \n{\n$enums\n}\ntypedef int $_ident1;", true);
  1619. replaceTokenSequence(tokens, "typedef enum $_ident1 $_ident1;", "/+ typedef enum $_ident1 $_ident1; +/", true);
  1620. replaceTokenSequence(tokens, "enum $_ident1 $_ident2", "$_ident1 $_ident2", true);
  1621. }
  1622. replaceTokenSequence(tokens, "typedef _Struct_size_bytes_($args)", "typedef", true);
  1623. replaceTokenSequence(tokens, "__struct_bcount($args)", "[__struct_bcount($args)]", true);
  1624. replaceTokenSequence(tokens, "struct $_ident : $_opt public $_ident2 {", "struct $_ident { $_ident2 base;", true);
  1625. replaceTokenSequence(tokens, "typedef struct { $data } $_ident2;",
  1626. "struct $_ident2\n{\n$data\n}", true);
  1627. replaceTokenSequence(tokens, "typedef struct { $data } $_ident2, $expr;",
  1628. "struct $_ident2\n{\n$data\n}\ntypedef $_ident2 $expr;", true);
  1629. replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $_ident2;",
  1630. "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2;", true);
  1631. replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $expr;",
  1632. "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true);
  1633. replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } $expr;",
  1634. "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true);
  1635. //replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } *$_ident2;",
  1636. // "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true);
  1637. //replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } *$_ident2;",
  1638. // "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true);
  1639. while(replaceTokenSequence(tokens, "struct { $data } $_ident2 $expr;",
  1640. "struct _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true) > 0) {}
  1641. replaceTokenSequence(tokens, "[$_expr1 uuid($_identIID) $_expr2] interface $_identClass : $_identBase {",
  1642. "dconst GUID IID_ __ $_identClass = $_identClass.iid;\n\n" ~
  1643. "interface $_identClass : $_identBase\n{\n static dconst GUID iid = $_identIID;\n\n", true);
  1644. replaceTokenSequence(tokens, "[$_expr1 uuid($IID) $_expr2] interface $_identClass : $_identBase {",
  1645. "dconst GUID IID_ __ $_identClass = $_identClass.iid;\n\n" ~
  1646. "interface $_identClass : $_identBase\n{\n static dconst GUID iid = { $IID };\n\n", true);
  1647. replaceTokenSequence(tokens, "[$_expr1 uuid($_identIID) $_expr2] coclass $_identClass {",
  1648. "dconst GUID CLSID_ __ $_identClass = $_identClass.iid;\n\n" ~
  1649. "class $_identClass\n{\n static dconst GUID iid = $_identIID;\n\n", true);
  1650. replaceTokenSequence(tokens, "[$_expr1 uuid($IID) $_expr2] coclass $_identClass {",
  1651. "dconst GUID CLSID_ __ $_identClass = $_identClass.iid;\n\n" ~
  1652. "interface $_identClass\n{\n static dconst GUID iid = { $IID };\n\n", true);
  1653. replaceTokenSequence(tokens, "coclass $_ident1 { $data }", "class $_ident1 { $data }", true);
  1654. // replaceTokenSequence(tokens, "assert $expr;", "assert($expr);", true);
  1655. replaceTokenSequence(tokens, "typedef union $_ident1 { $data } $_ident2 $expr;",
  1656. "union $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2 $expr;", true);
  1657. replaceTokenSequence(tokens, "typedef union $_ident1 switch($expr) $_ident2 { $data } $_ident3;",
  1658. "union $_ident3 /+switch($expr) $_ident2 +/ { $data };", true);
  1659. replaceTokenSequence(tokens, "typedef union switch($expr) { $data } $_ident3;",
  1660. "union $_ident3 /+switch($expr) +/ { $data };", true);
  1661. replaceTokenSequence(tokens, "union $_ident1 switch($expr) $_ident2 { $data };",
  1662. "union $_ident1 /+switch($expr) $_ident2 +/ { $data };", true);
  1663. replaceTokenSequence(tokens, "union $_ident1 switch($expr) $_ident2 { $data }",
  1664. "union $_ident1 /+switch($expr) $_ident2 +/ { $data }", true);
  1665. replaceTokenSequence(tokens, "case $_ident1:", "[case $_ident1:]", true);
  1666. replaceTokenSequence(tokens, "default:", "[default:]", true);
  1667. replaceTokenSequence(tokens, "union { $data } $_ident2 $expr;",
  1668. "union _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true);
  1669. replaceTokenSequence(tokens, "typedef struct $_ident1 $expr;", "typedef $_ident1 $expr;", true);
  1670. replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 $expr;", "typedef [$props] $_ident1 $expr;", true);
  1671. while (replaceTokenSequence(tokens, "typedef __nullterminated CONST $_identtype $_expr1, $args;",
  1672. "typedef __nullterminated CONST $_identtype $_expr1; typedef __nullterminated CONST $_identtype $args;", true) > 0) {}
  1673. while (replaceTokenSequence(tokens, "typedef CONST $_identtype $_expr1, $args;",
  1674. "typedef CONST $_identtype $_expr1; typedef CONST $_identtype $args;", true) > 0) {}
  1675. while (replaceTokenSequence(tokens, "typedef __nullterminated $_identtype $_expr1, $args;",
  1676. "typedef __nullterminated $_identtype $_expr1; typedef __nullterminated $_identtype $args;", true) > 0) {}
  1677. while (replaceTokenSequence(tokens, "typedef [$info] $_identtype $_expr1, $args;",
  1678. "typedef [$info] $_identtype $_expr1; typedef [$info] $_identtype $args;", true) > 0) {}
  1679. while (replaceTokenSequence(tokens, "typedef /+$info+/ $_identtype $_expr1, $args;",
  1680. "typedef /+$info+/ $_identtype $_expr1; typedef /+$info+/ $_identtype $args;", true) > 0) {}
  1681. while (replaceTokenSequence(tokens, "typedef $_identtype $_expr1, $args;",
  1682. "typedef $_identtype $_expr1; typedef $_identtype $args;", true) > 0) {}
  1683. while (replaceTokenSequence(tokens, "typedef void $_expr1, $args;",
  1684. "typedef void $_expr1; typedef void $args;", true) > 0) {}
  1685. replaceTokenSequence(tokens, "typedef $_ident1 $_ident1;", "", true);
  1686. replaceTokenSequence(tokens, "typedef interface $_ident1 $_ident1;", "", true);
  1687. // Remote/Local version are made final to avoid placing them into the vtbl
  1688. replaceTokenSequence(tokens, "[$pre call_as($arg) $post] $_not final", "[$pre call_as($arg) $post] final $_not", true);
  1689. // Some properties use the same name as the type of the return value
  1690. replaceTokenSequence(tokens, "$_identFun([$data] $_identFun $arg)", "$_identFun([$data] .$_identFun $arg)", true);
  1691. // properties that have identically named getter and setter methods have reversed vtbl entries,
  1692. // so we prepend put_,get_ or putref_ to the property
  1693. if(startsWith(currentModule, "debugger80"))
  1694. replaceTokenSequence(tokens, "HRESULT _stdcall", "HRESULT", true); // confusing following rules
  1695. replaceTokenSequence(tokens, "[$attr1 propput $attr2] HRESULT $_identFun", "[$attr1 propput $attr2]\n\tHRESULT put_ __ $_identFun", true);
  1696. replaceTokenSequence(tokens, "[$attr1 propget $attr2] HRESULT $_identFun", "[$attr1 propget $attr2]\n\tHRESULT get_ __ $_identFun", true);
  1697. replaceTokenSequence(tokens, "[$attr1 propputref $attr2] HRESULT $_identFun", "[$attr1 propputref $attr2]\n\tHRESULT putref_ __ $_identFun", true);
  1698. // VS2012 SDK
  1699. if(currentModule == "webproperties")
  1700. {
  1701. replaceTokenSequence(tokens, "ClassFileItem([$data] ProjectItem $arg)", "ClassFileItem([$data] .ProjectItem $arg)", true);
  1702. replaceTokenSequence(tokens, "Discomap([$data] ProjectItem $arg)", "Discomap([$data] .ProjectItem $arg)", true);
  1703. }
  1704. if(currentModule == "vsshell110")
  1705. {
  1706. // not inside #ifdef PROXYSTUB_BUILD
  1707. replaceTokenSequence(tokens, "alias IID_SVsFileMergeService SID_SVsFileMergeService;", "// $*", true);
  1708. replaceTokenSequence(tokens, "__uuidof(SVsHierarchyManipulation)", "SVsHierarchyManipulation.iid", true);
  1709. }
  1710. if(currentModule == "vsshell166")
  1711. {
  1712. replaceTokenSequence(tokens, "__uuidof(IVsDebuggerLaunchAsync)", "IVsDebuggerLaunchAsync.iid", true);
  1713. }
  1714. if(currentModule == "vapiemp")
  1715. {
  1716. // CLSID_CVapiEMPDataSource undefined, create one
  1717. replaceTokenSequence(tokens, "CVapiEMPDataSource.iid;", "uuid(\"{F1357394-9545-4cfd-AE2B-219C2A30C096}\");", true);
  1718. }
  1719. // interface without base class is used as namespace
  1720. replaceTokenSequence(tokens, "interface $_notIFace IUnknown { $_not static $data }",
  1721. "/+interface $_notIFace {+/ $_not $data /+} interface $_notIFace+/", true);
  1722. replaceTokenSequence(tokens, "dispinterface $_ident1 { $data }", "interface $_ident1 { $data }", true);
  1723. replaceTokenSequence(tokens, "module $_ident1 { $data }", "/+module $_ident1 {+/ $data /+}+/", true);
  1724. replaceTokenSequence(tokens, "properties:", "/+properties:+/", true);
  1725. replaceTokenSequence(tokens, "methods:", "/+methods:+/", true);
  1726. replaceTokenSequence(tokens, "(void)", "()", true);
  1727. replaceTokenSequence(tokens, "(VOID)", "()", true);
  1728. replaceTokenSequence(tokens, "[in] ref $_ident", "in $_ident*", true); // in passes by value otherwise
  1729. replaceTokenSequence(tokens, "[in,$data] ref $_ident", "[$data] in $_ident*", true); // in passes by value otherwise
  1730. replaceTokenSequence(tokens, "[in]", "in", true);
  1731. replaceTokenSequence(tokens, "[in,$_not out $data]", "[$_not $data] in", true);
  1732. replaceTokenSequence(tokens, "[$args1]in[$args2]in", "[$args1][$args2]in", true);
  1733. replaceTokenSequence(tokens, "in in", "in", true);
  1734. replaceTokenSequence(tokens, "[*]", "[0]", true);
  1735. replaceTokenSequence(tokens, "[default]", "/+[default]+/", true);
  1736. replaceExpressionTokens(tokens);
  1737. replaceTokenSequence(tokens, "__success($args)", "/+__success($args)+/", true);
  1738. version(all) {
  1739. replaceTokenSequence(tokens, "typedef const", "typedef CONST", true);
  1740. replaceTokenSequence(tokens, "extern \"C\"", "extern(C)", true);
  1741. replaceTokenSequence(tokens, "extern \"C++\"", "extern(C++)", true);
  1742. replaceTokenSequence(tokens, "__bcount($args)", "/+$*+/", true);
  1743. replaceTokenSequence(tokens, "__bcount_opt($args)", "/+$*+/", true);
  1744. replaceTokenSequence(tokens, "__in_bcount($args)", "/+$*+/", true);
  1745. replaceTokenSequence(tokens, "__in_ecount($args)", "/+$*+/", true);
  1746. replaceTokenSequence(tokens, "__in_xcount($args)", "/+$*+/", true);
  1747. replaceTokenSequence(tokens, "__in_bcount_opt($args)", "/+$*+/", true);
  1748. replaceTokenSequence(tokens, "__in_ecount_opt($args)", "/+$*+/", true);
  1749. replaceTokenSequence(tokens, "__out_bcount($args)", "/+$*+/", true);
  1750. replaceTokenSequence(tokens, "__out_xcount($args)", "/+$*+/", true);
  1751. replaceTokenSequence(tokens, "__out_bcount_opt($args)", "/+$*+/", true);
  1752. replaceTokenSequence(tokens, "__out_bcount_part($args)", "/+$*+/", true);
  1753. replaceTokenSequence(tokens, "__out_bcount_part_opt($args)", "/+$*+/", true);
  1754. replaceTokenSequence(tokens, "__out_bcount_full($args)", "/+$*+/", true);
  1755. replaceTokenSequence(tokens, "__out_ecount($args)", "/+$*+/", true);
  1756. replaceTokenSequence(tokens, "__out_ecount_opt($args)", "/+$*+/", true);
  1757. replaceTokenSequence(tokens, "__out_ecount_part($args)", "/+$*+/", true);
  1758. replaceTokenSequence(tokens, "__out_ecount_part_opt($args)", "/+$*+/", true);
  1759. replaceTokenSequence(tokens, "__out_ecount_full($args)", "/+$*+/", true);
  1760. replaceTokenSequence(tokens, "__out_data_source($args)", "/+$*+/", true);
  1761. replaceTokenSequence(tokens, "__out_xcount_opt($args)", "/+$*+/", true);
  1762. replaceTokenSequence(tokens, "__out_has_type_adt_props($args)", "/+$*+/", true);
  1763. replaceTokenSequence(tokens, "__inout_bcount($args)", "/+$*+/", true);
  1764. replaceTokenSequence(tokens, "__inout_ecount($args)", "/+$*+/", true);
  1765. replaceTokenSequence(tokens, "__inout_xcount($args)", "/+$*+/", true);
  1766. replaceTokenSequence(tokens, "__inout_bcount_opt($args)", "/+$*+/", true);
  1767. replaceTokenSequence(tokens, "__inout_ecount_opt($args)", "/+$*+/", true);
  1768. replaceTokenSequence(tokens, "__inout_bcount_part($args)", "/+$*+/", true);
  1769. replaceTokenSequence(tokens, "__inout_ecount_part($args)", "/+$*+/", true);
  1770. replaceTokenSequence(tokens, "__inout_bcount_part_opt($args)", "/+$*+/", true);
  1771. replaceTokenSequence(tokens, "__inout_ecount_part_opt($args)", "/+$*+/", true);
  1772. replaceTokenSequence(tokens, "__deref_out_ecount($args)", "/+$*+/", true);
  1773. replaceTokenSequence(tokens, "__deref_out_bcount($args)", "/+$*+/", true);
  1774. replaceTokenSequence(tokens, "__deref_out_xcount($args)", "/+$*+/", true);
  1775. replaceTokenSequence(tokens, "__deref_out_ecount_opt($args)", "/+$*+/", true);
  1776. replaceTokenSequence(tokens, "__deref_out_bcount_opt($args)", "/+$*+/", true);
  1777. replaceTokenSequence(tokens, "__deref_out_xcount_opt($args)", "/+$*+/", true);
  1778. replaceTokenSequence(tokens, "__deref_opt_out_bcount_full($args)", "/+$*+/", true);
  1779. replaceTokenSequence(tokens, "__deref_inout_ecount_z($args)", "/+$*+/", true);
  1780. replaceTokenSequence(tokens, "__field_bcount($args)", "/+$*+/", true);
  1781. replaceTokenSequence(tokens, "__field_bcount_opt($args)", "/+$*+/", true);
  1782. replaceTokenSequence(tokens, "__field_ecount($args)", "/+$*+/", true);
  1783. replaceTokenSequence(tokens, "__field_ecount_opt($args)", "/+$*+/", true);
  1784. replaceTokenSequence(tokens, "__in_range($args)", "/+$*+/", true);
  1785. replaceTokenSequence(tokens, "__range($args)", "/+$*+/", true);
  1786. replaceTokenSequence(tokens, "__declspec($args)", "/+$*+/", true);
  1787. replaceTokenSequence(tokens, "__in_range($args)", "/+$*+/", true);
  1788. replaceTokenSequence(tokens, "__transfer($args)", "/+$*+/", true);
  1789. replaceTokenSequence(tokens, "__drv_functionClass($args)", "/+$*+/", true);
  1790. replaceTokenSequence(tokens, "__drv_maxIRQL($args)", "/+$*+/", true);
  1791. replaceTokenSequence(tokens, "__drv_when($args)", "/+$*+/", true);
  1792. replaceTokenSequence(tokens, "__drv_freesMem($args)", "/+$*+/", true);
  1793. replaceTokenSequence(tokens, "__drv_preferredFunction($args)", "/+$*+/", true);
  1794. replaceTokenSequence(tokens, "__drv_allocatesMem($args)", "/+$*+/", true);
  1795. // Win SDK 8.0
  1796. replaceTokenSequence(tokens, "_IRQL_requires_same_", "/+$*+/", true);
  1797. replaceTokenSequence(tokens, "_Function_class_($args)", "/+$*+/", true);
  1798. replaceTokenSequence(tokens, "_Inout_cap_($args)", "/+$*+/", true);
  1799. replaceTokenSequence(tokens, "_Inout_count_($args)", "/+$*+/", true);
  1800. replaceTokenSequence(tokens, "_Inout_updates_($args)", "/+$*+/", true);
  1801. replaceTokenSequence(tokens, "_Inout_updates_z_($args)", "/+$*+/", true);
  1802. replaceTokenSequence(tokens, "_Inout_updates_opt_($args)", "/+$*+/", true);
  1803. replaceTokenSequence(tokens, "_Inout_updates_bytes_($args)", "/+$*+/", true);
  1804. replaceTokenSequence(tokens, "_Inout_updates_bytes_opt_($args)", "/+$*+/", true);
  1805. replaceTokenSequence(tokens, "_Inout_updates_bytes_to_opt_($args)", "/+$*+/", true);
  1806. replaceTokenSequence(tokens, "_Interlocked_operand_", "/+$*+/", true);
  1807. replaceTokenSequence(tokens, "_Struct_size_bytes_($args)", "/+$*+/", true);
  1808. replaceTokenSequence(tokens, "_Out_writes_($args)", "/+$*+/", true);
  1809. replaceTokenSequence(tokens, "_Out_writes_opt_($args)", "/+$*+/", true);
  1810. replaceTokenSequence(tokens, "_Out_writes_to_($args)", "/+$*+/", true);
  1811. replaceTokenSequence(tokens, "_Out_writes_to_opt_($args)", "/+$*+/", true);
  1812. replaceTokenSequence(tokens, "_Out_writes_bytes_($args)", "/+$*+/", true);
  1813. replaceTokenSequence(tokens, "_Out_writes_bytes_opt_($args)", "/+$*+/", true);
  1814. replaceTokenSequence(tokens, "_Out_writes_bytes_to_($args)", "/+$*+/", true);
  1815. replaceTokenSequence(tokens, "_Out_writes_bytes_to_opt_($args)", "/+$*+/", true);
  1816. replaceTokenSequence(tokens, "_Out_writes_bytes_all_($args)", "/+$*+/", true);
  1817. replaceTokenSequence(tokens, "_Out_cap_($args)", "/+$*+/", true);
  1818. replaceTokenSequence(tokens, "_Out_z_cap_($args)", "/+$*+/", true);
  1819. replaceTokenSequence(tokens, "_In_reads_($args)", "/+$*+/", true);
  1820. replaceTokenSequence(tokens, "_In_count_($args)", "/+$*+/", true);
  1821. replaceTokenSequence(tokens, "_In_reads_opt_($args)", "/+$*+/", true);
  1822. replaceTokenSequence(tokens, "_In_reads_bytes_($args)", "/+$*+/", true);
  1823. replaceTokenSequence(tokens, "_In_reads_bytes_opt_($args)", "/+$*+/", true);
  1824. replaceTokenSequence(tokens, "_In_NLS_string_($args)", "/+$*+/", true);
  1825. replaceTokenSequence(tokens, "_When_($args)", "/+$*+/", true);
  1826. replaceTokenSequence(tokens, "_At_($args)", "/+$*+/", true);
  1827. replaceTokenSequence(tokens, "_Post_readable_size_($args)", "/+$*+/", true);
  1828. replaceTokenSequence(tokens, "_Post_writable_byte_size_($args)", "/+$*+/", true);
  1829. replaceTokenSequence(tokens, "_Post_equal_to_($args)", "/+$*+/", true);
  1830. replaceTokenSequence(tokens, "_Ret_writes_maybenull_z_($args)", "/+$*+/", true);
  1831. replaceTokenSequence(tokens, "_Ret_writes_($args)", "/+$*+/", true);
  1832. replaceTokenSequence(tokens, "_Ret_range_($args)", "/+$*+/", true);
  1833. replaceTokenSequence(tokens, "_Return_type_success_($args)", "/+$*+/", true);
  1834. replaceTokenSequence(tokens, "_Outptr_result_buffer_($args)", "/+$*+/", true);
  1835. replaceTokenSequence(tokens, "_Outptr_result_bytebuffer_($args)", "/+$*+/", true);
  1836. replaceTokenSequence(tokens, "_Outptr_result_buffer_maybenull_($args)", "/+$*+/", true);
  1837. replaceTokenSequence(tokens, "_Outptr_opt_result_bytebuffer_all_($args)", "/+$*+/", true);
  1838. replaceTokenSequence(tokens, "_Outptr_opt_result_buffer_($args)", "/+$*+/", true);
  1839. replaceTokenSequence(tokens, "_Releases_exclusive_lock_($args)", "/+$*+/", true);
  1840. replaceTokenSequence(tokens, "_Releases_shared_lock_($args)", "/+$*+/", true);
  1841. replaceTokenSequence(tokens, "_Acquires_exclusive_lock_($args)", "/+$*+/", true);
  1842. replaceTokenSequence(tokens, "_Acquires_shared_lock_($args)", "/+$*+/", true);
  1843. // Win SDK 8.1
  1844. replaceTokenSequence(tokens, "_Post_satisfies_($args)", "/+$*+/", true);
  1845. replaceTokenSequence(tokens, "_Post_readable_byte_size_($args)", "/+$*+/", true);
  1846. replaceTokenSequence(tokens, "_Ret_reallocated_bytes_($args)", "/+$*+/", true);
  1847. // Win SDK 10.0
  1848. replaceTokenSequence(tokens, "_Translates_Win32_to_HRESULT_($args)", "/+$*+/", true);
  1849. replaceTokenSequence(tokens, "_Always_($args)", "/+$*+/", true);
  1850. replaceTokenSequence(tokens, "__control_entrypoint($args)", "/+$*+/", true);
  1851. replaceTokenSequence(tokens, "__assume_bound($args);", "/+$*+/", true);
  1852. replaceTokenSequence(tokens, "__asm{$args}$_opt;", "assert(false, \"asm not translated\"); asm{naked; nop; /+$args+/}", true);
  1853. replaceTokenSequence(tokens, "__asm $_not{$stmt}", "assert(false, \"asm not translated\"); asm{naked; nop; /+$_not $stmt+/} }", true);
  1854. replaceTokenSequence(tokens, "sizeof($_ident)", "$_ident.sizeof", true);
  1855. replaceTokenSequence(tokens, "sizeof($args)", "($args).sizeof", true);
  1856. // Win SDK 10.0,17136,0
  1857. replaceTokenSequence(tokens, "_Out_writes_z_($args)", "/+$*+/", true);
  1858. replaceTokenSequence(tokens, "_IRQL_requires_max_($args)", "/+$*+/", true);
  1859. // bitfields:
  1860. replaceTokenSequence(tokens, "$_identtype $_identname : $_num;", "__bf $_identtype, __quote $_identname __quote, $_num __eobf", true);
  1861. replaceTokenSequence(tokens, "$_identtype $_identname : $_ident;", "__bf $_identtype, __quote $_identname __quote, $_ident __eobf", true);
  1862. replaceTokenSequence(tokens, "$_identtype $_identname : $_num - $_identconst;", "__bf $_identtype, __quote $_identname __quote, $_num - $_identconst __eobf", true);
  1863. replaceTokenSequence(tokens, "$_identtype : $_num;", "__bf $_identtype, __quote __quote, $_num __eobf", true);
  1864. replaceTokenSequence(tokens, "__eobf __bf", ",\n\t", true);
  1865. replaceTokenSequence(tokens, "__bf", "mixin(bitfields!(", true);
  1866. replaceTokenSequence(tokens, "__eobf", "));", true);
  1867. // remove version between identifiers, must be declaration
  1868. while(replaceTokenSequence(tokens, "$_ident1 version(all) { $if } else { $else } $_ident2", "$_ident1 $if $_ident2", true) > 0
  1869. || replaceTokenSequence(tokens, "$_ident1 version(all) { $if } $_ident2", "$_ident1 $if $_ident2", true) > 0
  1870. || replaceTokenSequence(tokens, "$_ident1 version(none) { $if } else { $else } $_ident2", "$_ident1 $else $_ident2", true) > 0
  1871. || replaceTokenSequence(tokens, "$_ident1 version(none) { $if } $_ident2", "$_ident1 $_ident2", true) > 0) {}
  1872. // __stdcall
  1873. version(none)
  1874. {
  1875. replaceTokenSequence(tokens, "$_identtype NTAPI", "extern(Windows) $_identtype", true);
  1876. replaceTokenSequence(tokens, "$_identtype (NTAPI", "extern(Windows) $_identtype (", true);
  1877. replaceTokenSequence(tokens, "$_identtype WINAPI", "extern(Windows) $_identtype", true);
  1878. replaceTokenSequence(tokens, "$_identtype (WINAPI", "extern(Windows) $_identtype (", true);
  1879. replaceTokenSequence(tokens, "$_identtype (/+$_ident+/ WINAPI", "extern(Windows) $_identtype (", true);
  1880. replaceTokenSequence(tokens, "$_identtype APIENTRY", "extern(Windows) $_identtype", true);
  1881. replaceTokenSequence(tokens, "$_identtype (APIENTRY", "extern(Windows) $_identtype (", true);
  1882. replaceTokenSequence(tokens, "$_identtype (CALLBACK", "extern(Windows) $_identtype (", true);
  1883. } else {
  1884. replaceTokenSequence(tokens, "NTAPI", "extern(Windows)", true);
  1885. replaceTokenSequence(tokens, "WINAPI", "extern(Windows)", true);
  1886. replaceTokenSequence(tokens, "APIENTRY", "extern(Windows)", true);
  1887. replaceTokenSequence(tokens, "CALLBACK", "extern(Windows)", true);
  1888. }
  1889. replaceTokenSequence(tokens, "$_identtype extern(Windows)", "extern(Windows) $_identtype", true);
  1890. replaceTokenSequence(tokens, "$_identtype* extern(Windows)", "extern(Windows) $_identtype*", true);
  1891. replaceTokenSequence(tokens, "$_identtype (extern(Windows)", "extern(Windows) $_identtype (", true);
  1892. replaceTokenSequence(tokens, "$_identtype* (extern(Windows)", "extern(Windows) $_identtype* (", true);
  1893. replaceTokenSequence(tokens, "$_identtype (/+$_ident+/ extern(Windows)", "extern(Windows) $_identtype (", true);
  1894. replaceTokenSequence(tokens, "DECLARE_HANDLE($_ident);", "typedef HANDLE $_ident;", true);
  1895. replaceTokenSequence(tokens, "__inline $_identFun(", "inline int $_identFun(", true);
  1896. replaceTokenSequence(tokens, "HRESULT($_ident)($_args);", "HRESULT $_ident($_args);", true);
  1897. replaceTokenSequence(tokens, "$_identType (*$_identFunc)($_args)", "$_identType function($_args) $_identFunc", true);
  1898. replaceTokenSequence(tokens, "void* (*$_identFunc)($_args)", "void* function($_args) $_identFunc", true);
  1899. replaceTokenSequence(tokens, "$_identType (__stdcall *$_identFunc)($_args)", "$_identType __stdcall function($_args) $_identFunc", true);
  1900. replaceTokenSequence(tokens, "$_identType (__cdecl *$_identFunc)($_args)", "$_identType __cdecl function($_args) $_identFunc", true);
  1901. replaceTokenSequence(tokens, "$_identType (/+__cdecl+/ *$_identFunc)($_args)", "$_identType __cdecl function($_args) $_identFunc", true);
  1902. }
  1903. version(targetD2)
  1904. {
  1905. replaceTokenSequence(tokens, "$_ident const volatile*", "volatile dconst($_ident)*", true);
  1906. replaceTokenSequence(tokens, "CONST FAR*", "CONST*", true);
  1907. replaceTokenSequence(tokens, "$_ident const*", "dconst($_ident)*", true);
  1908. replaceTokenSequence(tokens, "const $_ident*", "dconst($_ident)*", true);
  1909. replaceTokenSequence(tokens, "CONST $_ident*", "dconst($_ident)*", true);
  1910. }
  1911. else
  1912. {
  1913. replaceTokenSequence(tokens, "const $_ident*", "/+const+/ $_ident*", true);
  1914. }
  1915. replaceTokenSequence(tokens, "in const $_not(", "in $_not", false);
  1916. if(currentModule == "vsshelluuids")
  1917. {
  1918. replaceTokenSequence(tokens, "denum GUID uuid_IVsDebugger3 = uuid($uid);$data denum GUID uuid_IVsDebugger3",
  1919. "$data\ndenum GUID uuid_IVsDebugger3",true);
  1920. replaceTokenSequence(tokens, "denum GUID uuid_IVsDebugLaunchHook = uuid($uid);$data denum GUID uuid_IVsDebugLaunchHook",
  1921. "$data\ndenum GUID uuid_IVsDebugLaunchHook",true);
  1922. }
  1923. if(currentModule == "mnuhelpids")
  1924. {
  1925. replaceTokenSequence(tokens, "denum icmdHelpManager = $data; denum icmdHelpManager", "denum icmdHelpManager", true);
  1926. }
  1927. if(currentModule == "prsht")
  1928. {
  1929. replaceTokenSequence(tokens, "alias _PROPSHEETPAGEA $_ident;", "alias $_ident _PROPSHEETPAGEA;", true);
  1930. replaceTokenSequence(tokens, "alias _PROPSHEETPAGEW $_ident;", "alias $_ident _PROPSHEETPAGEW;", true);
  1931. }
  1932. if(currentModule == "vsscceng")
  1933. {
  1934. replaceTokenSequence(tokens, "extern(C++) { $data }", "/+ $* +/", true);
  1935. }
  1936. if(currentModule == "winnls")
  1937. {
  1938. replaceTokenSequence(tokens, "alias MUI_CALLBACK_FLAG_UPGRADED_INSTALLATION $_ident;", "// $*", true);
  1939. }
  1940. if(currentModule == "basetsd")
  1941. {
  1942. // Deprecation: integral promotion not done for `~cast(ubyte)...`
  1943. replaceTokenSequence(tokens, "~MAXHALF_PTR", "~cast(int)MAXHALF_PTR", true);
  1944. replaceTokenSequence(tokens, "~(cast(UINT8)0)", "~0", true);
  1945. replaceTokenSequence(tokens, "~(cast(UINT16)0)", "~0", true);
  1946. replaceTokenSequence(tokens, "~MAXINT8", "~cast(int)MAXINT8", true);
  1947. replaceTokenSequence(tokens, "~MAXINT16", "~cast(int)MAXINT16", true);
  1948. }
  1949. //replaceTokenSequence(tokens, "[$args]", "\n\t\t/+[$args]+/", true);
  1950. TokenIterator inAlias = tokens.end();
  1951. for(TokenIterator tokIt = tokens.begin(); !tokIt.atEnd(); ++tokIt)
  1952. {
  1953. Token tok = *tokIt;
  1954. //tok.pretext = tok.pretext.replace("//D", "");
  1955. tok.text = translateToken(tok.text);
  1956. if(tok.text == "[" && tokIt[1].text == "]")
  1957. {
  1958. if(tokIt[2].text == ";")
  1959. tokIt[1].pretext ~= "0"; // in struct
  1960. else if(tokIt[2].text == "," || tokIt[2].text == ")" && tokIt[-1].type == Token.Identifier)
  1961. {
  1962. tok.text = "";
  1963. tokIt[1].text = "";
  1964. tokIt[-1].pretext ~= "*"; // in function argument
  1965. }
  1966. }
  1967. else if(tok.text == "[" && tokIt[1].text != "]")
  1968. {
  1969. if((tokIt.atBegin() || tokIt[-1].text != "{" || tokIt[-2].text != "=") &&
  1970. (tokIt[1].type != Token.Number || tokIt[2].text != "]") &&
  1971. (tokIt[2].text != "]" || tokIt[3].text != ";"))
  1972. {
  1973. TokenIterator bit = tokIt;
  1974. //if(advanceToClosingBracket(bit) && bit.text != ";")
  1975. {
  1976. if(tokIt.atBegin || (tokIt[-1].text != "(" && tokIt[-1].text != "alias"))
  1977. if (tok.pretext.indexOf('\n') < 0)
  1978. tok.pretext ~= "\n\t\t";
  1979. tok.text = "/+[";
  1980. }
  1981. }
  1982. }
  1983. else if(tok.text == "]" && tokIt[-1].text != "[")
  1984. {
  1985. TokenIterator openit = tokIt;
  1986. if(retreatToOpeningBracket(openit) &&
  1987. (openit.atBegin || (openit-1).atBegin || openit[-1].text != "{" || openit[-2].text != "="))
  1988. if((tokIt[-1].type != Token.Number || tokIt[-2].text != "[") &&
  1989. (tokIt[-2].text != "[" || tokIt[1].text != ";"))
  1990. tok.text = "]+/";
  1991. }
  1992. else if(tok.text == "struct" && tokIt[1].type == Token.Identifier && tokIt[2].text != "{")
  1993. {
  1994. if(tokIt[1].text != "__" && tokIt[1].text != "_")
  1995. {
  1996. // forward reference to struct type
  1997. tok.text = "";
  1998. if(tokIt[1].text.startsWith("tag"))
  1999. tokIt[1].text = tokIt[1].text[3..$];
  2000. }
  2001. }
  2002. else if((tok.text == "GUID" || tok.text == "IID" || tok.text == "CLSID") &&
  2003. tokIt[1].type == Token.Identifier && tokIt[2].text == "=" && tokIt[3].text == "{")
  2004. {
  2005. convertGUID(tokIt + 4);
  2006. }
  2007. else if(tok.text == "__quote")
  2008. {
  2009. tok.pretext = "";
  2010. tok.text = "\"";
  2011. tokIt[1].pretext = "";
  2012. }
  2013. else if(tok.text == "*" && !tokIt.atBegin() && isClassIdentifier(tokIt[-1].text))
  2014. {
  2015. tok.text = "";
  2016. if(tok.pretext.empty && tokIt[1].pretext.empty)
  2017. tok.pretext = " ";
  2018. }
  2019. else if(tok.type == Token.String && tok.text.length > 4 && tok.text[0] == '\'')
  2020. tok.text = "\"" ~ tok.text[1 .. $-1] ~ "\"";
  2021. else if(tok.text == "in" && (tokIt[1].text in classes))
  2022. tok.text = "/+[in]+/";
  2023. else if(tok.text == "alias")
  2024. inAlias = tokIt;
  2025. else if(tok.text == ";" && !inAlias.atEnd())
  2026. {
  2027. if(tokIt[-1].type == Token.Identifier)
  2028. {
  2029. if (string* s = tokIt[-1].text in aliases)
  2030. {
  2031. if(*s != currentFullModule)
  2032. {
  2033. inAlias.pretext ~= "/+";
  2034. tok.text ~= "+/";
  2035. if(!currentImports.contains(*s))
  2036. addedImports.addunique(*s);
  2037. }
  2038. }
  2039. else
  2040. aliases[tokIt[-1].text] = currentFullModule;
  2041. }
  2042. inAlias = tokens.end();
  2043. }
  2044. }
  2045. // vsshell.idl:
  2046. replaceTokenSequence(tokens, "DEFINE_GUID($_ident,$_num1,$_num2,$_num3,$_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB)",
  2047. "const GUID $_ident = { $_num1,$_num2,$_num3, [ $_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB ] }", true);
  2048. replaceTokenSequence(tokens, "EXTERN_GUID($_ident,$_num1,$_num2,$_num3,$_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB)",
  2049. "const GUID $_ident = { $_num1,$_num2,$_num3, [ $_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB ] }", true);
  2050. // VS 16.6: untranslatable C++
  2051. replaceTokenSequence(tokens, "idl_bool IsLegacyVTIntPtrVARIANT $code GetVSCOOKIEVariantValHelper($args) { $code2 }",
  2052. "", false);
  2053. // combaseapi.h:
  2054. replaceTokenSequence(tokens, "alias int $_ident = $_num;", "enum int $_ident = $_num;", true);
  2055. // C style array declarations to S style
  2056. replaceTokenSequence(tokens, "$_identtype $_identvar[$dim]", "$_identtype[$dim] $_identvar", true);
  2057. replaceTokenSequence(tokens, "$_identtype[$dim1] $_identvar[$dim2]", "$_identtype[$dim1][$dim2] $_identvar", true);
  2058. // handle some pointer array explicitely to avoid ambiguities with expressions
  2059. replaceTokenSequence(tokens, "void* $_identvar[$dim]", "void*[$dim] $_identvar", true);
  2060. replaceTokenSequence(tokens, "ubyte* $_identvar[$dim]", "ubyte*[$dim] $_identvar", true);
  2061. replaceTokenSequence(tokens, "ushort* $_identvar[$dim]", "ushort*[$dim] $_identvar", true);
  2062. replaceTokenSequence(tokens, "UUID* $_identvar[$dim]", "UUID*[$dim] $_identvar", true);
  2063. replaceTokenSequence(tokens, "RPC_IF_ID* $_identvar[$dim]", "RPC_IF_ID*[$dim] $_identvar", true);
  2064. string txt = tokenListToString(tokens, true);
  2065. return txt;
  2066. }
  2067. string translateToken(string text)
  2068. {
  2069. switch(text)
  2070. {
  2071. case "denum": return "enum";
  2072. case "dconst": return "const";
  2073. case "_stdcall": return "/*_stdcall*/";
  2074. case "_fastcall": return "/*_fastcall*/";
  2075. case "__stdcall": return "/*__stdcall*/";
  2076. case "__cdecl": return "/*__cdecl*/";
  2077. case "__gdi_entry": return "/*__gdi_entry*/";
  2078. //case "const": return "/*const*/";
  2079. case "inline": return "/*inline*/";
  2080. case "__int64": return "long";
  2081. case "__int32": return "int";
  2082. case "__int3264": return "int";
  2083. case "long": return "int";
  2084. case "typedef": return "alias";
  2085. case "bool": return "idl_bool";
  2086. case "GUID_NULL": return "const_GUID_NULL";
  2087. case "NULL": return "null";
  2088. case "scope": return "idl_scope";
  2089. // winbase annotations
  2090. case "__in":
  2091. case "__in_opt":
  2092. case "__in_z_opt":
  2093. case "__in_bound":
  2094. case "__allocator":
  2095. case "__out":
  2096. case "__out_opt":
  2097. case "__out_z":
  2098. case "__inout":
  2099. case "__inout_z":
  2100. case "__deref":
  2101. case "__deref_inout_opt":
  2102. case "__deref_out_opt":
  2103. case "__deref_inout":
  2104. case "__inout_opt":
  2105. case "__deref_out":
  2106. case "__deref_opt_out":
  2107. case "__deref_opt_out_opt":
  2108. case "__deref_opt_inout_opt":
  2109. case "__callback":
  2110. case "__format_string":
  2111. case "__reserved":
  2112. case "__notnull":
  2113. case "__nullterminated":
  2114. case "__nullnullterminated":
  2115. case "__possibly_notnullterminated":
  2116. case "__drv_interlocked":
  2117. case "__drv_sameIRQL":
  2118. case "__drv_inTry":
  2119. case "__drv_aliasesMem":
  2120. case "__post":
  2121. case "__notvalid":
  2122. case "__analysis_noreturn":
  2123. // Windows SDK 8.0
  2124. case "_Outptr_":
  2125. case "_Outptr_opt_":
  2126. case "_COM_Outptr_":
  2127. case "_In_z_":
  2128. case "_In_opt_z_":
  2129. case "_Pre_":
  2130. case "_Pre_valid_":
  2131. case "_Pre_z_":
  2132. case "_Pre_opt_valid_":
  2133. case "_Pre_maybenull_":
  2134. case "_Post_valid_":
  2135. case "_Post_invalid_":
  2136. case "_Post_":
  2137. case "_Post_z_":
  2138. case "_Deref_opt_out_opt_":
  2139. case "_Post_equals_last_error_":
  2140. case "_Outptr_opt_result_maybenull_":
  2141. case "_Check_return_":
  2142. case "_Must_inspect_result_":
  2143. case "_Frees_ptr_opt_":
  2144. case "_Reserved_":
  2145. case "_Ret_maybenull_":
  2146. case "_Ret_opt_":
  2147. case "_Printf_format_string_":
  2148. // Windows SDK 8.1
  2149. case "_Field_z_":
  2150. case "_Pre_notnull_":
  2151. case "_Frees_ptr_":
  2152. // Windows SDK 10.0
  2153. case "NOT_BUILD_WINDOWS_DEPRECATE":
  2154. case "DECLSPEC_ALLOCATOR":
  2155. // Windows SDK 10.0.14393.0
  2156. case "_Outptr_result_z_":
  2157. // Windows SDK 10.0.15063.0
  2158. case "_Post_ptr_invalid_":
  2159. // VS14 SDK comment after #endif
  2160. case "PROXYSTUB_BUILD":
  2161. return "/*" ~ text ~ "*/";
  2162. case "__checkReturn": return "/*__checkReturn*/";
  2163. case "volatile": return "/*volatile*/";
  2164. case "__inline": return "/*__inline*/";
  2165. case "__forceinline": return "/*__forceinline*/";
  2166. case "IN": return "/*IN*/";
  2167. case "OUT": return "/*OUT*/";
  2168. case "NEAR": return "/*NEAR*/";
  2169. case "FAR": return "/*FAR*/";
  2170. case "HUGEP": return "/*HUGEP*/";
  2171. case "OPTIONAL": return "/*OPTIONAL*/";
  2172. case "DECLSPEC_NORETURN": return "/*DECLSPEC_NORETURN*/";
  2173. case "CONST": return "/*CONST*/";
  2174. case "VOID": return "void";
  2175. case "wchar_t": return "wchar";
  2176. case "->": return ".";
  2177. // vslangproj.d
  2178. case "prjBuildActionCustom": return "prjBuildActionEmbeddedResource";
  2179. // wingdi.d: wrong octal number in SDK v6.0A
  2180. case "02500": return "2500";
  2181. default:
  2182. if(string* ps = text in tokImports)
  2183. text = *ps ~ "." ~ text;
  2184. break;
  2185. }
  2186. return text;
  2187. }
  2188. void addSource(string file)
  2189. {
  2190. string base = baseName(file);
  2191. if(excludefiles.contains(base))
  2192. return;
  2193. if(!srcfiles.contains(file))
  2194. srcfiles ~= file;
  2195. }
  2196. void addSourceByPattern(string file)
  2197. {
  2198. SpanMode mode = SpanMode.shallow;
  2199. if (file[0] == '+')
  2200. {
  2201. mode = SpanMode.depth;
  2202. file = file[1..$];
  2203. }
  2204. string path = dirName(file);
  2205. string pattern = baseName(file);
  2206. foreach (string name; dirEntries(path, mode))
  2207. if (globMatch(baseName(name), pattern))
  2208. {
  2209. addSource(name);
  2210. if (pattern[0] != '*')
  2211. break; // don't add optional files twice
  2212. }
  2213. }
  2214. void addSources(string file)
  2215. {
  2216. if (indexOf(file, '*') >= 0 || indexOf(file, '?') >= 0)
  2217. addSourceByPattern("+" ~ file);
  2218. else
  2219. {
  2220. if(!exists(file))
  2221. file = dirName(file) ~ "\\shared\\" ~ baseName(file);
  2222. if(!exists(file))
  2223. file = replace(file, "\\shared\\", "\\um\\");
  2224. addSource(file);
  2225. }
  2226. }
  2227. string fileToModule(string file)
  2228. {
  2229. auto len = file.startsWith(win_d_path) ? win_d_path.length : vsi_d_path.length;
  2230. file = file[len .. $];
  2231. if (_endsWith(file,".d"))
  2232. file = file[0 .. $-2];
  2233. file = replace(file, "/", ".");
  2234. file = replace(file, "\\", ".");
  2235. return file;
  2236. }
  2237. string makehdr(string file, string d_file)
  2238. {
  2239. string pkg = d_file.startsWith(win_d_path) ? packageWin : packageVSI;
  2240. string name = fileToModule(d_file);
  2241. string hdr;
  2242. hdr ~= "// File generated by idl2d from\n";
  2243. hdr ~= "// " ~ file ~ "\n";
  2244. hdr ~= "module " ~ pkg ~ name ~ ";\n\n";
  2245. //hdr ~= "import std.c.windows.windows;\n";
  2246. //hdr ~= "import std.c.windows.com;\n";
  2247. //hdr ~= "import idl.pp_util;\n";
  2248. if(pkg == packageVSI)
  2249. hdr ~= "import " ~ packageNF ~ "vsi;\n";
  2250. else
  2251. hdr ~= "import " ~ packageNF ~ "base;\n";
  2252. hdr ~= "\n";
  2253. foreach(imp; addedImports)
  2254. hdr ~= "import " ~ imp ~ ";\n";
  2255. if(currentModule == "vsshell")
  2256. hdr ~= "import " ~ packageWin ~ "commctrl;\n";
  2257. if(currentModule == "vsshlids")
  2258. hdr ~= "import " ~ packageVSI ~ "oleipc;\n";
  2259. else if(currentModule == "debugger80")
  2260. hdr ~= "import " ~ packageWin ~ "oaidl;\n"
  2261. ~ "import " ~ packageVSI ~ "dte80a;\n";
  2262. else if(currentModule == "xmldomdid")
  2263. hdr ~= "import " ~ packageWin ~ "idispids;\n";
  2264. else if(currentModule == "xmldso")
  2265. hdr ~= "import " ~ packageWin ~ "xmldom;\n";
  2266. else if(currentModule == "commctrl")
  2267. hdr ~= "import " ~ packageWin ~ "objidl;\n";
  2268. else if(currentModule == "shellapi")
  2269. hdr ~= "import " ~ packageWin ~ "iphlpapi;\n";
  2270. else if(currentModule == "ifmib")
  2271. hdr ~= "import " ~ packageWin ~ "iprtrmib;\n";
  2272. else if(currentModule == "ipmib")
  2273. hdr ~= "import " ~ packageWin ~ "iprtrmib;\n";
  2274. else if(currentModule == "tcpmib")
  2275. hdr ~= "import " ~ packageWin ~ "iprtrmib;\n";
  2276. else if(currentModule == "udpmib")
  2277. hdr ~= "import " ~ packageWin ~ "iprtrmib;\n";
  2278. else if(currentModule == "vssolutn")
  2279. hdr ~= "import " ~ packageWin ~ "winnls;\n";
  2280. else if(currentModule == "dpa_dsa")
  2281. hdr ~= "import " ~ packageWin ~ "objidlbase;\n";
  2282. hdr ~= "\n";
  2283. version(static_if_to_version)
  2284. {
  2285. version(remove_pp) {} else
  2286. hdr ~= "version = pp_ifndef;\n\n";
  2287. }
  2288. return hdr;
  2289. }
  2290. void rewrite_vsiproject(string sources)
  2291. {
  2292. string projfile = sdk_d_path ~ "vsi.visualdproj";
  2293. if(!exists(projfile))
  2294. return;
  2295. string txt = cast(string)(std.file.read(projfile));
  2296. auto pos = indexOf(txt, "<Folder");
  2297. if(pos < 0)
  2298. return;
  2299. auto pos2 = indexOf(txt[pos .. $], '\n');
  2300. if(pos < 0)
  2301. return;
  2302. string ins = " <Folder name=\"port\">\n";
  2303. string portdir = sdk_d_path ~ "port";
  2304. foreach (string name; dirEntries(portdir, SpanMode.shallow))
  2305. if (globMatch(baseName(name), "*.d"))
  2306. ins ~= " <File path=\"port\\" ~ baseName(name) ~ "\" />\n";
  2307. string folder = "port";
  2308. string[] files = split(sources);
  2309. foreach(file; files)
  2310. {
  2311. if(file == "\\" || file == "SRC" || file == "=")
  2312. continue;
  2313. string dir = dirName(file);
  2314. if(dir != folder)
  2315. {
  2316. ins ~= " </Folder>\n";
  2317. ins ~= " <Folder name=\"" ~ dir ~ "\">\n";
  2318. folder = dir;
  2319. }
  2320. ins ~= " <File path=\"" ~ file ~ "\" />\n";
  2321. }
  2322. ins ~= " </Folder>\n";
  2323. ins ~= " </Folder>\n";
  2324. ins ~= "</DProject>\n";
  2325. string xml = txt[0 .. pos + pos2 + 1] ~ ins;
  2326. if (xml != txt)
  2327. std.file.write(projfile, xml);
  2328. }
  2329. void setCurrentFile(string file)
  2330. {
  2331. currentFile = file;
  2332. currentFullModule = fixImport(file);
  2333. auto p = lastIndexOf(currentFullModule, '.');
  2334. if(p >= 0)
  2335. currentModule = currentFullModule[p+1 .. $];
  2336. else
  2337. currentModule = currentFullModule;
  2338. addedImports = addedImports.init;
  2339. currentImports = currentImports.init;
  2340. string[string] reinit;
  2341. tokImports = reinit; // tokImports.init; dmd bugzilla #3491
  2342. }
  2343. int main(string[] argv)
  2344. {
  2345. if(argv.length <= 1)
  2346. {
  2347. writeln("usage: ", baseName(argv[0]), " {-vsi|-dte|-win|-sdk|-prefix|-verbose|-define} [files...]");
  2348. writeln();
  2349. writeln(" -vsi=DIR specify path to Visual Studio Integration SDK");
  2350. writeln(" -dte=DIR specify path to additional IDL files from VSI SDK");
  2351. writeln(" -win=DIR specify path to Windows SDK include folder");
  2352. writeln(" -sdk=DIR output base directory for Windows/VSI SDK files");
  2353. writeln(" -prefix=P prefix used for identifiers that are D keywords");
  2354. writeln(" -verbose report undefined definitions in preprocessor conditions");
  2355. writeln();
  2356. writeln("Example: ", baseName(argv[0]), ` test.idl`);
  2357. writeln(" ", baseName(argv[0]), ` -win="%WindowsSdkDir%\Include" -vsi="%VSSDK110Install%" -sdk=sdk`);
  2358. return -1;
  2359. }
  2360. getopt(argv,
  2361. "vsi", &vsi_base_path,
  2362. "dte", &dte_path,
  2363. "win", &win_path,
  2364. "sdk", &sdk_d_path,
  2365. "prefix", &keywordPrefix,
  2366. "verbose", &verbose);
  2367. dte_path = replace(dte_path, "/", "\\");
  2368. win_path = replace(win_path, "/", "\\");
  2369. sdk_d_path = replace(sdk_d_path, "/", "\\");
  2370. if(!dte_path.empty && !_endsWith(dte_path, "\\"))
  2371. dte_path ~= "\\";
  2372. if(!win_path.empty && !_endsWith(win_path, "\\"))
  2373. win_path ~= "\\";
  2374. if(!sdk_d_path.empty && !_endsWith(sdk_d_path, "\\"))
  2375. sdk_d_path ~= "\\";
  2376. if(!vsi_base_path.empty)
  2377. {
  2378. vsi_path = vsi_base_path ~ r"\VisualStudioIntegration\Common\IDL\";
  2379. vsi_hpath = vsi_base_path ~ r"\VisualStudioIntegration\Common\Inc\";
  2380. }
  2381. if(!sdk_d_path.empty)
  2382. {
  2383. vsi_d_path = sdk_d_path ~ dirVSI ~ r"\";
  2384. win_d_path = sdk_d_path ~ dirWin ~ r"\";
  2385. }
  2386. initFiles();
  2387. // GC.disable();
  2388. disabled_defines["__VARIANT_NAME_1"] = 1;
  2389. disabled_defines["__VARIANT_NAME_2"] = 1;
  2390. disabled_defines["__VARIANT_NAME_3"] = 1;
  2391. disabled_defines["__VARIANT_NAME_4"] = 1;
  2392. disabled_defines["uuid_constant"] = 1;
  2393. // declared twice
  2394. disabled_defines["VBProjectProperties2"] = 1;
  2395. disabled_defines["VBProjectConfigProperties2"] = 1; // declared twice
  2396. disabled_defines["IID_ProjectProperties2"] = 1;
  2397. disabled_defines["IID_ProjectConfigurationProperties2"] = 1;
  2398. // bad init
  2399. disabled_defines["DOCDATAEXISTING_UNKNOWN"] = 1;
  2400. disabled_defines["HIERARCHY_DONTCHANGE"] = 1;
  2401. disabled_defines["SELCONTAINER_DONTCHANGE"] = 1;
  2402. disabled_defines["HIERARCHY_DONTPROPAGATE"] = 1;
  2403. disabled_defines["SELCONTAINER_DONTPROPAGATE"] = 1;
  2404. disabled_defines["ME_UNKNOWN_MENU_ITEM"] = 1;
  2405. disabled_defines["ME_FIRST_MENU_ITEM"] = 1;
  2406. // win sdk
  2407. disabled_defines["pascal"] = 1;
  2408. disabled_defines["WINBASEAPI"] = 1;
  2409. disabled_defines["WINADVAPI"] = 1;
  2410. disabled_defines["FORCEINLINE"] = 1;
  2411. //disabled_defines["POINTER_64"] = 1;
  2412. disabled_defines["UNALIGNED"] = 1;
  2413. disabled_defines["RESTRICTED_POINTER"] = 1;
  2414. disabled_defines["RTL_CONST_CAST"] = 1;
  2415. disabled_defines["RTL_RUN_ONCE_INIT"] = 1;
  2416. disabled_defines["RTL_SRWLOCK_INIT"] = 1;
  2417. disabled_defines["RTL_CONDITION_VARIABLE_INIT"] = 1;
  2418. // commctrl.h
  2419. disabled_defines["HDM_TRANSLATEACCELERATOR"] = 1;
  2420. foreach(string file; argv[1..$])
  2421. addSources(file);
  2422. writeln("Searching files...");
  2423. if(!win_path.empty)
  2424. foreach(pat; win_idl_files)
  2425. addSources(win_path ~ pat);
  2426. if(!vsi_path.empty)
  2427. foreach(pat; vsi_idl_files)
  2428. addSources(vsi_path ~ pat);
  2429. if(!vsi_hpath.empty)
  2430. foreach(pat; vsi_h_files)
  2431. addSources(vsi_hpath ~ pat);
  2432. if(!dte_path.empty)
  2433. foreach(pat; dte_idl_files)
  2434. addSources(dte_path ~ pat);
  2435. writeln("Scanning files...");
  2436. Source[] srcs;
  2437. foreach(string file; srcfiles)
  2438. {
  2439. Source src = new Source;
  2440. src.filename = file;
  2441. src.text = fromMBSz (cast(immutable(char)*)(cast(char[]) read(file) ~ "\0").ptr);
  2442. try
  2443. {
  2444. // bad qquoting in VS2019 SDK
  2445. if (file.endsWith("vsshell100.idl"))
  2446. src.text = src.text.replace(`(\"VSProjectLoadPriority is deprecated\")`, `("VSProjectLoadPriority is deprecated")`);
  2447. if (file.endsWith("vsshell150.idl"))
  2448. src.text = src.text.replace(`(\"VSSOLUTIONDEFERREDLOADOPTION is deprecated\")`, `("VSSOLUTIONDEFERREDLOADOPTION is deprecated")`);
  2449. src.tokens = scanText(src.text, 1, true);
  2450. }
  2451. catch(Exception e)
  2452. {
  2453. e.msg = file ~ e.msg;
  2454. throw e;
  2455. }
  2456. collectClasses(src.tokens);
  2457. srcs ~= src;
  2458. }
  2459. classes["IUnknown"] = true;
  2460. classes["IServiceProvider"] = true;
  2461. writeln("Converting files...");
  2462. string sources = "SRC = \\\n";
  2463. foreach(Source src; srcs)
  2464. {
  2465. string d_file;
  2466. d_file = replace(src.filename, win_path, win_d_path);
  2467. d_file = replace(d_file, vsi_path, vsi_d_path);
  2468. d_file = replace(d_file, vsi_hpath, vsi_d_path);
  2469. d_file = replace(d_file, dte_path, vsi_d_path);
  2470. d_file = toLower(d_file);
  2471. if(d_file._endsWith(".idl") || d_file._endsWith(".idh"))
  2472. d_file = d_file[0 .. $-3] ~ "d";
  2473. if(d_file.endsWith(".h"))
  2474. d_file = d_file[0 .. $-1] ~ "d";
  2475. d_file = translateFilename(d_file);
  2476. setCurrentFile(d_file);
  2477. writeln(src.filename, " -> ", d_file);
  2478. string text = convertText(src.tokens);
  2479. text = removeDuplicateEmptyLines(text);
  2480. string hdr = makehdr(src.filename, d_file);
  2481. std.file.write(d_file, toUTF8(hdr ~ text));
  2482. sources ~= "\t" ~ d_file[sdk_d_path.length .. $] ~ " \\\n";
  2483. }
  2484. sources ~= "\n";
  2485. if(!sdk_d_path.empty)
  2486. {
  2487. version(vsi)
  2488. string srcfile = sdk_d_path ~ "\\vsi_sources";
  2489. else
  2490. string srcfile = sdk_d_path ~ "\\sources";
  2491. std.file.write(srcfile, sources);
  2492. rewrite_vsiproject(sources);
  2493. }
  2494. return 0;
  2495. }
  2496. bool verbose;
  2497. bool simple = true;
  2498. string[] srcfiles;
  2499. string[] excludefiles;
  2500. string currentFile;
  2501. string currentModule;
  2502. string currentFullModule;
  2503. }
  2504. ///////////////////////////////////////////////////////////////////////
  2505. void testConvert(string txt, string exptxt, string mod = "")
  2506. {
  2507. txt = replace(txt, "\r", "");
  2508. exptxt = replace(exptxt, "\r", "");
  2509. idl2d inst = new idl2d;
  2510. inst.currentModule = mod;
  2511. TokenList tokens = scanText(txt, 1, true);
  2512. string ntxt = inst.convertText(tokens);
  2513. assert(ntxt == exptxt);
  2514. }
  2515. unittest
  2516. {
  2517. string txt = q{
  2518. typedef struct tag { } TAG;
  2519. };
  2520. string exptxt = q{
  2521. struct tag
  2522. {
  2523. }
  2524. alias tag TAG;
  2525. };
  2526. testConvert(txt, exptxt);
  2527. }
  2528. unittest
  2529. {
  2530. string txt = q{
  2531. cpp_quote("//;end_internal")
  2532. cpp_quote("typedef struct tagELEMDESC {")
  2533. cpp_quote(" TYPEDESC tdesc; /* the type of the element */")
  2534. cpp_quote(" union {")
  2535. cpp_quote(" IDLDESC idldesc; /* info for remoting the element */")
  2536. cpp_quote(" PARAMDESC paramdesc; /* info about the parameter */")
  2537. cpp_quote(" };")
  2538. cpp_quote("} ELEMDESC, * LPELEMDESC;")
  2539. };
  2540. string exptxt = q{
  2541. //;end_internal
  2542. struct tagELEMDESC
  2543. {
  2544. TYPEDESC tdesc; /* the type of the element */
  2545. union {
  2546. IDLDESC idldesc; /* info for remoting the element */
  2547. PARAMDESC paramdesc; /* info about the parameter */
  2548. };
  2549. }
  2550. alias tagELEMDESC ELEMDESC; alias tagELEMDESC * LPELEMDESC;
  2551. };
  2552. testConvert(txt, exptxt);
  2553. }
  2554. ///////////////////////////////////////////////////////////////////////
  2555. unittest
  2556. {
  2557. string txt = q{
  2558. int x;
  2559. cpp_quote("#ifndef WIN16")
  2560. typedef struct tagSIZE
  2561. {
  2562. LONG cx;
  2563. LONG cy;
  2564. } SIZE, *PSIZE, *LPSIZE;
  2565. cpp_quote("#else // WIN16")
  2566. cpp_quote("typedef struct tagSIZE")
  2567. cpp_quote("{")
  2568. cpp_quote(" INT cx;")
  2569. cpp_quote(" INT cy;")
  2570. cpp_quote("} SIZE, *PSIZE, *LPSIZE;")
  2571. cpp_quote("#endif // WIN16")
  2572. };
  2573. version(remove_pp)
  2574. string exptxt = q{
  2575. int x;
  2576. struct tagSIZE
  2577. {
  2578. LONG cx;
  2579. LONG cy;
  2580. }
  2581. alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; } ~ q{
  2582. // WIN16
  2583. };
  2584. else // !remove_pp
  2585. string exptxt = q{
  2586. int x;
  2587. version(all) /* #ifndef WIN16 */ {
  2588. struct tagSIZE
  2589. {
  2590. LONG cx;
  2591. LONG cy;
  2592. }
  2593. alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE;
  2594. } else { // #else // WIN16
  2595. struct tagSIZE
  2596. {
  2597. INT cx;
  2598. INT cy;
  2599. }
  2600. alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE;
  2601. } // #endif // WIN16
  2602. };
  2603. testConvert(txt, exptxt);
  2604. }
  2605. ///////////////////////////////////////////////////////////////////////
  2606. unittest
  2607. {
  2608. string txt = "
  2609. int x;
  2610. #if defined(MIDL_PASS)
  2611. typedef struct _LARGE_INTEGER {
  2612. #else // MIDL_PASS
  2613. typedef union _LARGE_INTEGER {
  2614. struct { };
  2615. #endif //MIDL_PASS
  2616. LONGLONG QuadPart;
  2617. } LARGE_INTEGER;
  2618. ";
  2619. string exptxt = "
  2620. int x;
  2621. union _LARGE_INTEGER
  2622. {
  2623. struct { }; LONGLONG QuadPart;
  2624. }
  2625. alias _LARGE_INTEGER LARGE_INTEGER;
  2626. ";
  2627. testConvert(txt, exptxt, "winnt");
  2628. }
  2629. ///////////////////////////////////////////////////////////////////////
  2630. unittest
  2631. {
  2632. string txt = "
  2633. #define convert() \\
  2634. hello
  2635. #define noconvert(n,m) \\
  2636. hallo1 |\\
  2637. hallo2
  2638. ";
  2639. string exptxt = "
  2640. int convert() { return " ~ "
  2641. hello; }
  2642. // #define noconvert(n,m) \\
  2643. // hallo1 |\\
  2644. // hallo2
  2645. ";
  2646. version(macro2template) exptxt = replace(exptxt, "int", "auto");
  2647. testConvert(txt, exptxt);
  2648. }
  2649. unittest
  2650. {
  2651. string txt = "
  2652. #define CONTEXT_i386 0x00010000L // this assumes that i386 and
  2653. #define CONTEXT_CONTROL (CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP
  2654. ";
  2655. string exptxt = "
  2656. enum CONTEXT_i386 = 0x00010000; // this assumes that i386 and
  2657. enum CONTEXT_CONTROL = (CONTEXT_i386 | 0x00000001); // SS:SP, CS:IP, FLAGS, BP
  2658. ";
  2659. testConvert(txt, exptxt);
  2660. }
  2661. unittest
  2662. {
  2663. string txt = "
  2664. #define NtCurrentTeb() ((struct _TEB *)_rdtebex())
  2665. ";
  2666. string exptxt = "
  2667. _TEB* NtCurrentTeb() { return ( cast( _TEB*)_rdtebex()); }
  2668. ";
  2669. version(macro2template) exptxt = replace(exptxt, "_TEB* ", "auto ");
  2670. testConvert(txt, exptxt);
  2671. }
  2672. unittest
  2673. {
  2674. string txt = "
  2675. enum { prjBuildActionNone }
  2676. cpp_quote(\"#define prjBuildActionMin prjBuildActionNone\")
  2677. cpp_quote(\"#define prjBuildActionMax prjBuildActionCustom\")
  2678. ";
  2679. string exptxt = "
  2680. enum { prjBuildActionNone }
  2681. enum prjBuildActionMin = prjBuildActionNone;
  2682. alias prjBuildActionEmbeddedResource prjBuildActionMax;
  2683. ";
  2684. testConvert(txt, exptxt);
  2685. }
  2686. unittest
  2687. {
  2688. string txt = "
  2689. #define _INTEGRAL_MAX_BITS 64
  2690. #if (!defined (_MAC) && (!defined(MIDL_PASS) || defined(__midl)) && (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64)))
  2691. typedef __int64 LONGLONG;
  2692. #endif
  2693. ";
  2694. string exptxt = "
  2695. alias long LONGLONG;
  2696. ";
  2697. // testConvert(txt, exptxt);
  2698. }
  2699. unittest
  2700. {
  2701. string txt = "
  2702. #define KEY_READ ((STANDARD_RIGHTS_READ |\\
  2703. KEY_QUERY_VALUE)\\
  2704. & (~SYNCHRONIZE))
  2705. ";
  2706. string exptxt = "
  2707. enum KEY_READ = ((STANDARD_RIGHTS_READ |
  2708. KEY_QUERY_VALUE)
  2709. & (~SYNCHRONIZE));
  2710. ";
  2711. testConvert(txt, exptxt);
  2712. }
  2713. unittest
  2714. {
  2715. string txt = "
  2716. #if _WIN32_WINNT >= 0x0600
  2717. #define _PROPSHEETPAGEA_V3 _PROPSHEETPAGEA
  2718. #elif (_WIN32_IE >= 0x0400)
  2719. #define _PROPSHEETPAGEA_V2 _PROPSHEETPAGEA
  2720. #else
  2721. #define _PROPSHEETPAGEA_V1 _PROPSHEETPAGEA
  2722. #endif
  2723. ";
  2724. string exptxt = "
  2725. version(all) /* #if _WIN32_WINNT >= 0x0600 */ {
  2726. alias _PROPSHEETPAGEA_V3 _PROPSHEETPAGEA;
  2727. } else version(all) /* #elif (_WIN32_IE >= 0x0400) */ {
  2728. alias _PROPSHEETPAGEA_V2 _PROPSHEETPAGEA;
  2729. } else {
  2730. alias _PROPSHEETPAGEA_V1 _PROPSHEETPAGEA;
  2731. } " ~ "
  2732. ";
  2733. testConvert(txt, exptxt, "prsht");
  2734. }
  2735. unittest
  2736. {
  2737. string txt = "
  2738. #define PtrToPtr64( p ) ((void * POINTER_64) p)
  2739. __inline
  2740. void * POINTER_64 PtrToPtr64(const void *p)
  2741. {
  2742. return((void * POINTER_64) (unsigned __int64) (ULONG_PTR)p );
  2743. }
  2744. ";
  2745. string exptxt = "
  2746. // #define PtrToPtr64( p ) ((void * POINTER_64) p)
  2747. /*__inline*/
  2748. void * PtrToPtr64(const( void)*p)
  2749. {
  2750. return( cast(void*) cast(ulong)cast(ULONG_PTR)p );
  2751. }
  2752. ";
  2753. testConvert(txt, exptxt, "prsht");
  2754. }
  2755. unittest
  2756. {
  2757. string txt = "int x[3];";
  2758. string exptxt = "int[3] x;";
  2759. testConvert(txt, exptxt);
  2760. }
  2761. unittest
  2762. {
  2763. string txt = "struct __declspec(deprecated(\"deprecated\")) S;\n";
  2764. string exp = "/+ struct /+__declspec(deprecated(\"deprecated\"))+/ S; +/\n";
  2765. testConvert(txt, exp);
  2766. }