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 17 import c2d.tokenizer; 18 import c2d.tokutil; 19 import c2d.dgutil; 20 21 import std.string; 22 import std.file; 23 import std.path; 24 import std.stdio; 25 import std.ascii; 26 import std.algorithm; 27 import std.getopt; 28 import std.utf; 29 import std.array; 30 import std.windows.charset; 31 import core.memory; 32 33 version(linux) 34 string fromMBSz(immutable(char)* a) { 35 import arsd.characterencodings; 36 import core.stdc.string; 37 auto it = a[0 .. strlen(a)]; 38 return convertToUtf8(cast(immutable(ubyte[])) it, "windows-1252"); 39 } 40 41 version = remove_pp; 42 version = static_if_to_version; 43 version = vsi; 44 version = macro2template; 45 version = targetD2; 46 //version = Win8; 47 48 class Source 49 { 50 string filename; 51 string text; 52 TokenList tokens; 53 } 54 55 // endsWith does not work reliable and crashes on page end 56 bool _endsWith(string s, string e) 57 { 58 return (s.length >= e.length && s[$-e.length .. $] == e); 59 } 60 61 alias std..string.indexOf indexOf; 62 63 class idl2d 64 { 65 /////////////////////////////////////////////////////// 66 // configuration 67 version(Win8) 68 { 69 string vsi_base_path = r"c:\l\vs9SDK"; // r"c:\l\vs9SDK"; 70 string dte_path = r"m:\s\d\visuald\trunk\sdk\vsi\idl\"; 71 string win_path = r"c:\l\vs11\Windows Kits\8.0\Include\"; 72 string sdk_d_path = r"m:\s\d\visuald\trunk\sdk\"; 73 } 74 else version(all) 75 { 76 string vsi_base_path; 77 string dte_path; 78 string win_path; 79 string sdk_d_path; 80 } 81 else version(all) 82 { 83 string vsi_base_path = r"c:\l\vs9SDK"; 84 string dte_path = r"m:\s\d\visuald\trunk\sdk\vsi\idl\"; 85 string win_path = r"c:\Programme\Microsoft SDKs\Windows\v6.0A\Include\"; 86 string sdk_d_path = r"m:\s\d\visuald\trunk\sdk\"; 87 } 88 else 89 { 90 string vsi_base_path = r"c:\Program Files\Microsoft Visual Studio 2010 SDK"; // r"c:\l\vs9SDK"; 91 string dte_path = r"c:\s\d\visuald\trunk\sdk\vsi\idl\"; 92 string win_path = r"c:\Program Files\Microsoft SDKs\Windows\v7.1\Include\"; 93 string sdk_d_path = r"c:\s\d\visuald\trunk\sdk\"; 94 } 95 96 static const string dirVSI = "vsi"; 97 static const string dirWin = "win32"; 98 99 string packageVSI = "sdk." ~ dirVSI ~ "."; 100 string packageWin = "sdk." ~ dirWin ~ "."; 101 string packageNF = "sdk.port."; 102 string keywordPrefix = "sdk_"; 103 104 string vsi_path; // = vsi_base_path ~ r"\VisualStudioIntegration\Common\IDL\"; 105 string vsi_hpath; // = vsi_base_path ~ r"\VisualStudioIntegration\Common\Inc\"; 106 107 string vsi_d_path; // = sdk_d_path ~ r"vsi\"; 108 string win_d_path; // = sdk_d_path ~ r"win32\"; 109 110 string[] win_idl_files; 111 string[] vsi_idl_files; 112 string[] vsi_h_files; 113 string[] dte_idl_files; 114 115 version(vsi) bool vsi = true; 116 else bool vsi = false; 117 118 void initFiles() 119 { 120 win_idl_files = [ "windef.h", "sdkddkver.h", "basetsd.h", "ntstatus.h", 121 "winnt.h", "winbase.h", "winuser.h", "ktmtypes.h", 122 "winerror.h", "winreg.h", "reason.h", "commctrl.h", 123 "wingdi.h", "prsht.h", 124 "iphlpapi.h", "iprtrmib.h", "ipexport.h", "iptypes.h", "tcpestats.h", 125 /*"inaddr.h", "in6addr.h",*/ 126 "ipifcons.h", "ipmib.h", "tcpmib.h", "udpmib.h", 127 "ifmib.h", "ifdef.h", "nldef.h", "winnls.h", 128 "shellapi.h", "rpcdce.h" /*, "rpcdcep.h"*/ ]; 129 130 win_idl_files ~= [ "unknwn.idl", "oaidl.idl", "wtypes.idl", "oleidl.idl", 131 "ocidl.idl", "objidl.idl", "docobj.idl", "oleauto.h", "objbase.h", 132 "mshtmcid.h", "xmldom.idl", "xmldso.idl", "xmldomdid.h", "xmldsodid.h", "idispids.h", 133 "activdbg.id*", "activscp.id*", "dbgprop.id*", // only available in Windows SDK v7.x 134 ]; 135 136 // only available (and are required for successfull compilation) in Windows SDK v8 137 foreach(f; [ "wtypesbase.idl", 138 //"winapifamily.h", "apisetcconv.h", "apiset.h", // commented because it is difficult to convert this file 139 "minwinbase.h", "processenv.h", 140 "minwindef.h", "fileapi.h", "debugapi.h", "handleapi.h", "errhandlingapi.h", 141 "fibersapi.h", "namedpipeapi.h", "profileapi.h", "heapapi.h", "synchapi.h", 142 "interlockedapi.h", "processthreadsapi.h", "sysinfoapi.h", "memoryapi.h", 143 "threadpoollegacyapiset.h", "utilapiset.h", "ioapiset.h", 144 "threadpoolprivateapiset.h", "threadpoolapiset.h", "bemapiset.h", "wow64apiset.h", 145 "jobapi.h", "timezoneapi.h", "datetimeapi.h", "stringapiset.h", 146 "libloaderapi.h", "securitybaseapi.h", "namespaceapi.h", "systemtopologyapi.h", "processtopologyapi.h", 147 "securityappcontainer.h", "realtimeapiset.h", "unknwnbase.idl", "objidlbase.idl", "combaseapi.h", 148 // Win SDK 8.1 149 "mprapidef.h", "lmerr.h", "lmcons.h", 150 // Win SDK 10.0 151 "coml2api.h", "jobapi2.h", "propidlbase.idl", 152 // Win SDK 10.0.10586.0 153 "enclaveapi.h", 154 // Win SDK 10.0.14393.0 155 "dpa_dsa.h", 156 // Win SDK 10.0.18362.0 157 "fileapifromapp.h", 158 ]) 159 win_idl_files ~= f ~ "*"; // make it optional 160 161 if(vsi) 162 { 163 vsi_idl_files = [ "shared.idh", "vsshell.idl", "*.idl", "*.idh" ]; 164 vsi_h_files = [ "completionuuids.h", "contextuuids.h", "textmgruuids.h", "vsshelluuids.h", "vsdbgcmd.h", 165 "venusids.h", "stdidcmd.h", "vsshlids.h", "mnuhelpids.h", "WCFReferencesIds.h", 166 "vsdebugguids.h", "VSRegKeyNames.h", "SCGuids.h", "wbids.h", "sharedids.h", 167 "vseeguids.h", "version.h", "scc.h", 168 "vsplatformuiuuids.*", // only in VS2010 SDK 169 "vscookie.*", // only in later VS2017 SDK 170 // no longer in SDK2010: "DSLToolsCmdID.h", 171 ]; 172 173 dte_idl_files = [ "*.idl" ]; 174 } 175 } 176 177 // see also preDefined, isExpressionToken, convertDefine, convertText, translateToken 178 /////////////////////////////////////////////////////// 179 180 string[string] tokImports; 181 int[string] disabled_defines; 182 int[string] disabled_ifdef; 183 string[string] converted_defines; 184 bool[] pp_enable_stack; 185 string[] elif_braces_stack; 186 bool convert_next_cpp_quote = true; 187 bool cpp_quote_in_comment = false; 188 bool[string] classes; 189 string[string] aliases; 190 bool[string] enums; 191 192 string[] currentImports; 193 string[] addedImports; 194 195 void reinsert_cpp_quote(ref TokenIterator tokIt) 196 { 197 TokenIterator it = tokIt; 198 string text; 199 while(!it.atEnd() && it.text == "cpp_quote") 200 { 201 assert(it[1].text == "("); 202 assert(it[2].type == Token.String); 203 assert(it[3].text == ")"); 204 text ~= it.pretext; 205 text ~= strip(it[2].text[1..$-1]); 206 it += 4; 207 } 208 bool endsWithBS = text.endsWith("\\") != 0; 209 bool quote = text.indexOf("\\\n") >= 0 || endsWithBS || !convert_next_cpp_quote; 210 if(quote) 211 text = tokIt.pretext ~ "/+" ~ text[tokIt.pretext.length .. $] ~ "+/"; 212 convert_next_cpp_quote = !endsWithBS; 213 214 TokenList tokens = scanText(text, tokIt.lineno, true); 215 tokIt.eraseUntil(it); 216 tokIt = insertTokenList(tokIt, tokens); 217 } 218 219 bool handle_cpp_quote(ref TokenIterator tokIt, bool inEnum) 220 { 221 // tokIt on "cpp_quote" 222 TokenIterator it = tokIt; 223 assert(it[1].text == "("); 224 assert(it[2].type == Token.String); 225 assert(it[3].text == ")"); 226 string text = strip(it[2].text[1..$-1]); 227 228 string txt = text; 229 bool convert = convert_next_cpp_quote; 230 convert_next_cpp_quote = true; 231 232 if(cpp_quote_in_comment || text.startsWith("/*")) 233 { 234 txt = replace(text, "\\\"", "\""); 235 cpp_quote_in_comment = (text.indexOf("*/") < 0); 236 } 237 else if(text.startsWith("//")) 238 txt = replace(text, "\\\"", "\""); 239 else if(text.endsWith("\\")) // do not convert multi-line #define 240 { 241 convert_next_cpp_quote = false; 242 convert = false; 243 } 244 else if(text.startsWith("#")) 245 { 246 txt = replace(txt, "\\\"", "\""); 247 txt = convertPP(txt, tokIt.lineno, inEnum); 248 } 249 250 if(convert) 251 { 252 string pretext = tokIt.pretext; 253 tokIt.erase(); 254 tokIt.erase(); 255 tokIt.erase(); 256 tokIt.erase(); 257 258 txt = cpp_string(txt); 259 TokenList tokens = scanText(txt, tokIt.lineno, false); 260 tokIt = insertTokenList(tokIt, tokens); 261 tokIt.pretext = pretext ~ tokIt.pretext; 262 } 263 else 264 tokIt.pretext ~= "// "; 265 266 return convert; 267 } 268 269 void reinsertTextTokens(ref TokenIterator tokIt, string text) 270 { 271 string pretext; 272 if(!tokIt.atEnd()) 273 { 274 pretext = tokIt.pretext; 275 tokIt.erase(); 276 } 277 TokenList tokens = scanText(text, tokIt.lineno, false); 278 tokIt = insertTokenList(tokIt, tokens); 279 tokIt.pretext = pretext ~ tokIt.pretext; 280 } 281 282 bool isExpressionToken(TokenIterator tokIt, bool first) 283 { 284 int type = tokIt.type; 285 switch(type) 286 { 287 case Token.Identifier: 288 switch(tokIt.text) 289 { 290 case "_far": 291 case "_pascal": 292 case "_cdecl": 293 case "void": 294 return false; 295 default: 296 return !(tokIt.text in disabled_defines); 297 } 298 case Token.String: 299 case Token.Number: 300 case Token.ParenL: 301 case Token.BracketL: 302 case Token.BraceL: 303 return true; 304 case Token.ParenR: 305 case Token.BracketR: 306 case Token.BraceR: 307 if(!first) 308 return tokIt.type != Token.Identifier && tokIt.type != Token.Number && tokIt.type != Token.ParenL; 309 return !first; 310 case Token.Equal: 311 case Token.Unequal: 312 case Token.LessThan: 313 case Token.LessEq: 314 case Token.GreaterThan: 315 case Token.GreaterEq: 316 case Token.Shl: 317 case Token.Shr: 318 case Token.Ampersand: 319 case Token.Assign: 320 case Token.Dot: 321 case Token.Div: 322 case Token.Mod: 323 case Token.Xor: 324 case Token.Or: 325 case Token.OrOr: 326 case Token.AmpAmpersand: 327 return !first; 328 case Token.Plus: 329 case Token.Minus: 330 case Token.Asterisk: 331 case Token.Tilde: 332 return true; // can be unary or binary operator 333 case Token.Colon: 334 case Token.Question: 335 if(vsi) 336 goto default; 337 return !first; 338 339 case Token.Comma: 340 return !first && !(tokIt + 1).atEnd() && tokIt[1].type != Token.EOF; 341 342 case Token.Struct: 343 // struct at beginning of a cast? 344 if(!tokIt.atBegin() && tokIt[-1].type == Token.ParenL) 345 return true; 346 return false; 347 348 default: 349 return false; 350 } 351 } 352 353 bool hasBalancedBrackets(TokenIterator start, TokenIterator end) 354 { 355 int[] brackets; 356 while (start != end) 357 { 358 int type = start.type; 359 switch(type) 360 { 361 case Token.ParenL: 362 case Token.BracketL: 363 case Token.BraceL: 364 brackets ~= type; 365 break; 366 case Token.ParenR: 367 if (brackets.empty || brackets[$-1] != Token.ParenL) 368 return false; 369 brackets = brackets[0..$-1]; 370 break; 371 case Token.BracketR: 372 if (brackets.empty || brackets[$-1] != Token.BracketL) 373 return false; 374 brackets = brackets[0..$-1]; 375 break; 376 case Token.BraceR: 377 if (brackets.empty || brackets[$-1] != Token.BraceL) 378 return false; 379 brackets = brackets[0..$-1]; 380 break; 381 default: 382 break; 383 } 384 start++; 385 } 386 return brackets.empty; 387 } 388 389 bool isExpression(TokenIterator start, TokenIterator end) 390 { 391 if(start == end || start.type == Token.EOF) 392 return false; 393 if(!isExpressionToken(start, true)) 394 return false; 395 for(TokenIterator it = start + 1; it != end && !it.atEnd() && it.type != Token.EOF; ++it) 396 if(!isExpressionToken(it, false)) 397 return false; 398 return hasBalancedBrackets(start, end); 399 } 400 401 bool isPrimaryExpr(TokenIterator it) 402 { 403 if(it.atEnd()) 404 return false; 405 if(it.text == "(" || it.type == Token.Number || it.type == Token.Identifier) 406 return true; 407 return false; 408 } 409 410 string getExpressionType(string ident, TokenIterator start, TokenIterator end) 411 { 412 while(start != end && start.text == "(" && start[1].text == "(") 413 ++start; 414 if(start.text == "(" && start[1].type == Token.Identifier && start[2].text == ")" && isPrimaryExpr(start + 3)) 415 return start[1].text; 416 if(start.text == "(" && start[1].type == Token.Identifier && start[2].text == "*" && start[3].text == ")" 417 && isPrimaryExpr(start + 4)) 418 return start[1].text ~ start[2].text; 419 if(start.text == "(" && start[1].text == "struct" && start[2].type == Token.Identifier && start[3].text == "*" && start[4].text == ")" 420 && isPrimaryExpr(start + 5)) 421 return start[2].text ~ start[3].text; 422 return "int"; 423 } 424 425 string getArgumentType(string ident, TokenIterator start, TokenIterator end, string rettype) 426 { 427 switch(ident) 428 { 429 case "IS_INTRESOURCE": 430 case "MAKEINTRESOURCEA": 431 case "MAKEINTRESOURCEW": 432 case "MAKEINTATOM": 433 return "int"; 434 default: 435 return rettype; 436 } 437 } 438 439 void collectClasses(TokenList tokens) 440 { 441 for(TokenIterator tokIt = tokens.begin(); tokIt != tokens.end; ++tokIt) 442 if(tokIt.text == "class" || tokIt.text == "interface" || tokIt.text == "coclass") 443 classes[tokIt[1].text] = true; 444 } 445 446 bool isClassIdentifier(string ident) 447 { 448 if(ident in classes) 449 return true; 450 return false; 451 } 452 453 // 1: yes, 0: undecided, -1: no 454 int _preDefined(string cond) 455 { 456 switch(cond) 457 { 458 case "FALSE": 459 return -2; // not defined for expression, but for #define 460 461 case "_WIN64": 462 return 4; // special cased 463 case "0": 464 case "MAC": 465 case "_MAC": 466 case "_WIN32_WCE": 467 case "_IA64_": 468 case "_M_AMD64": 469 case "RC_INVOKED": 470 case "MIDL_PASS": 471 case "DO_NO_IMPORTS": 472 case "_IMM_": 473 case "NONAMELESSUNION": 474 case "WIN16": 475 case "INTEROPLIB": 476 case "__INDENTSTYLE__": 477 case "__CTC__": 478 case "_CTC_GUIDS_": 479 case "CTC_INVOKED": 480 case "VS_PACKAGE_INCLUDE": 481 case "URTBUILD": 482 case "NOGUIDS": 483 case "SHOW_INCLUDES": 484 case "RGS_INVOKED": 485 case "__RE_E_DEFINED__": 486 case "OLE2ANSI": 487 488 // for winbase 489 case "STRICT": 490 case "_M_CEE": 491 case "_M_CEE_PURE": 492 case "_DCOM_OA_REMOTING_": 493 case "_DCOM_OC_REMOTING_": 494 case "_SLIST_HEADER_": 495 case "_RTL_RUN_ONCE_DEF": 496 case "__midl": 497 498 // Windows SDK 8.0 499 case "NOAPISET": 500 return -1; 501 502 case "WINAPI": 503 case "WINAPI_INLINE": 504 case "APIENTRY": 505 case "NTAPI": 506 case "NTAPI_INLINE": 507 case "interface": 508 case "PtrToPtr64": 509 case "Ptr64ToPtr": 510 case "HandleToHandle64": 511 case "Handle64ToHandle": 512 return 3; // predefined for #define, but not in normal text 513 case "TRUE": 514 return 2; // predefined for expression, but not for #define 515 case "1": 516 case "__cplusplus": 517 case "UNICODE": 518 case "DEFINE_GUID": 519 case "UNIX": 520 case "_X86_": 521 case "_M_IX86": 522 case "MULTIPLE_WATCH_WINDOWS": 523 case "PROXYSTUB_BUILD": 524 case "(defined(_WIN32)||defined(_WIN64))&&!defined(OLE2ANSI)": 525 case "defined(_INTEGRAL_MAX_BITS)&&_INTEGRAL_MAX_BITS>=64": // needed to define LONGLONG 526 case "!defined SENTINEL_Reason": // reason.h 527 528 //case "!defined(CTC_INVOKED)&&!defined(RGS_INVOKED)": 529 //case "!defined(_DCOM_OA_REMOTING_)&&!defined(_DCOM_OC_REMOTING_)": 530 //case "!defined(_DCOM_OA_REMOTING_)": 531 //case "!defined(_DCOM_OC_REMOTING_)": 532 case "_HRESULT_DEFINED": 533 // case "_PALETTEENTRY_DEFINED": 534 // case "_LOGPALETTE_DEFINED": 535 case "_REFPOINTS_DEFINED": 536 case "COMBOX_SANDBOX": 537 538 // defined to avoid #define translation 539 case "MAKE_HRESULT": 540 case "CBPCLIPDATA": 541 //case "FACILITY_ITF": 542 case "PFN_TSHELL_TMP": 543 case "V_INT_PTR": 544 case "VT_INT_PTR": 545 case "V_UINT_PTR": 546 case "VT_UINT_PTR": 547 case "PKGRESETFLAGS": 548 case "VSLOCALREGISTRYROOTHANDLE_TO_HKEY": 549 case "DTE": 550 case "Project": 551 case "ProjectItem": 552 case "CodeModel": 553 case "FileCodeModel": 554 case "IDebugMachine2_V7": 555 case "EnumMachines_V7": 556 case "IEnumDebugMachines2_V7": 557 case "IID_IEnumDebugMachines2_V7": 558 559 // defined with both enum and #define in ipimb.h 560 case "MIB_IPROUTE_TYPE_OTHER": 561 case "MIB_IPROUTE_TYPE_INVALID": 562 case "MIB_IPROUTE_TYPE_DIRECT": 563 case "MIB_IPROUTE_TYPE_INDIRECT": 564 565 case "NULL": 566 case "VOID": 567 case "CONST": 568 case "CALLBACK": 569 case "NOP_FUNCTION": 570 case "DECLARE_HANDLE": 571 case "STDMETHODCALLTYPE": 572 case "STDMETHODVCALLTYPE": 573 case "STDAPICALLTYPE": 574 case "STDAPIVCALLTYPE": 575 case "STDMETHODIMP": 576 case "STDMETHODIMP_": 577 case "STDOVERRIDEMETHODIMP": 578 case "STDOVERRIDEMETHODIMP_": 579 case "IFACEMETHODIMP": 580 case "IFACEMETHODIMP_": 581 case "STDMETHODIMPV": 582 case "STDMETHODIMPV_": 583 case "STDOVERRIDEMETHODIMPV": 584 case "STDOVERRIDEMETHODIMPV_": 585 case "IFACEMETHODIMPV": 586 case "IFACEMETHODIMPV_": 587 case "_WIN32_WINNT": 588 case "GetLastError": 589 case "MF_END": // defined twice in winuser.h, but said to be obsolete 590 case "__int3264": 591 return 1; 592 593 case "_NO_SCRIPT_GUIDS": // used in activdbg.h, disable to avoid duplicate GUID definitions 594 case "EnumStackFramesEx": // used in activdbg.h, but in wrong scope 595 case "SynchronousCallIntoThread": // used in activdbg.h, but in wrong scope 596 return 1; 597 598 // winnt.h 599 case "_WINDEF_": 600 case "_WINBASE_": 601 //if(vsi) 602 // return 1; 603 break; 604 case "_WIN32": 605 //if(!vsi) 606 return 1; 607 //break; 608 609 // Windows SDK 8.0 610 case "_CONTRACT_GEN": 611 return -1; 612 613 // Windows SDK 10.0.15063.0 614 case "RPC_UNICODE_SUPPORTED": 615 return 1; 616 case "_M_HYBRID_X86_ARM64": 617 return -1; 618 619 // Windows SDK 10.0.17134.0 620 case "IMAGE_POLICY_METADATA_NAME": 621 return 1; 622 623 // SDK 10.0.17763.0 624 case "EN_SEARCHWEB": 625 case "RtlGetNonVolatileToken": 626 case "RtlFreeNonVolatileToken": 627 case "RtlFlushNonVolatileMemory": 628 case "RtlDrainNonVolatileFlush": 629 case "RtlWriteNonVolatileMemory": 630 case "RtlFlushNonVolatileMemoryRanges": 631 return 1; 632 633 default: 634 break; 635 } 636 637 // header double include protection 638 if(_endsWith(cond, "_DEFINED") || 639 _endsWith(cond, "_INCLUDED") || 640 _endsWith(cond, "_h__") || 641 _endsWith(cond, "_H__") || 642 _endsWith(cond, "_H_") || 643 startsWith(cond, "_INC_") || 644 _endsWith(cond, "_IDH")) 645 return -1; 646 647 if(cond == "_" ~ toUpper(currentModule) ~ "_") 648 return -1; 649 650 if(startsWith(cond, "WINAPI_FAMILY_PARTITION")) 651 return 1; 652 653 if(indexOf(cond, "(") < 0 && indexOf(cond, "|") < 0 && indexOf(cond, "&") < 0) 654 { 655 if (startsWith(cond, "CMD_ZOOM_")) 656 return 1; 657 658 cond = cond.replace(" ", ""); 659 if(startsWith(cond, "WINVER>") || startsWith(cond, "_WIN32_WINNT>") || startsWith(cond, "NTDDI_VERSION>")) 660 return 1; 661 if(startsWith(cond, "WINVER<") || startsWith(cond, "_WIN32_WINNT<") || startsWith(cond, "NTDDI_VERSION<")) 662 return -1; 663 if(startsWith(cond, "_MSC_VER>") || startsWith(cond, "_MSC_FULL_VER>")) 664 return -1; // disable all msc specials 665 if(startsWith(cond, "_MSC_VER<") || startsWith(cond, "_MSC_FULL_VER<")) 666 return 1; // disable all msc specials 667 if(startsWith(cond, "_WIN32_IE>")) 668 return 1; // assue newest IE 669 if(startsWith(cond, "NO")) 670 return -1; // used to disable parts, we want it all 671 } 672 return 0; 673 } 674 675 int findLogicalOp(string cond, string op) 676 { 677 int paren = 0; 678 for(int i = 0; i <= cond.length - op.length; i++) 679 { 680 if(paren == 0 && cond[i .. i+op.length] == op) 681 return i; 682 if(cond[i] == '(') 683 paren++; 684 else if(cond[i] == ')') 685 paren--; 686 } 687 return -1; 688 } 689 690 int preDefined(string cond) 691 { 692 int sign = 1; 693 694 for( ; ; ) 695 { 696 int rc = _preDefined(cond); 697 if(rc != 0) 698 return sign * rc; 699 700 if(startsWith(cond, "(") && _endsWith(cond, ")") && findLogicalOp(cond[1..$], ")") == cond.length - 2) 701 cond = cond[1..$-1]; 702 else if(startsWith(cond, "defined(") && findLogicalOp(cond[8..$], ")") == cond.length - 9) 703 cond = cond[8..$-1]; 704 else if(startsWith(cond, "!") && indexOf(cond[1..$-1], "&") < 0 && indexOf(cond[1..$-1], "|") < 0) 705 { 706 cond = cond[1..$]; 707 sign = -sign; 708 } 709 else 710 { 711 int idx = findLogicalOp(cond, "||"); 712 if(idx < 0) 713 idx = findLogicalOp(cond, "&&"); 714 if(idx >= 0) 715 { 716 int rc1 = preDefined(cond[0..idx]); 717 int rc2 = preDefined(cond[idx+2..$]); 718 if(cond[idx] == '|') 719 return rc1 > 0 || rc2 > 0 ? 1 : rc1 < 0 && rc2 < 0 ? -1 : 0; 720 else // '&' 721 return rc1 > 0 && rc2 > 0 ? 1 : rc1 < 0 || rc2 < 0 ? -1 : 0; 722 } 723 break; 724 } 725 } 726 return 0; 727 } 728 729 int preDefined(TokenIterator start, TokenIterator end) 730 { 731 string txt = tokenListToString(start, end, false, true); 732 int rc = preDefined(txt); 733 734 if(rc == 0 && verbose) 735 writefln("\"" ~ txt ~ "\" not defined/undefined"); 736 return rc; 737 } 738 739 void handleCondition(TokenIterator tokIt, TokenIterator lastIt, string pp) 740 { 741 string elif_braces; 742 int predef = preDefined(tokIt + 1, lastIt + 1); 743 if(pp == "pp_ifndef") 744 predef = -predef; 745 if(predef < 0) 746 { 747 string ver = (predef == -4 ? "Win32" : "none"); 748 tokIt.text = "version(" ~ ver ~ ") /* " ~ tokIt.text; 749 lastIt.text ~= " */ {/+"; 750 elif_braces = "+/} "; 751 } 752 else if(predef > 0) 753 { 754 string ver = (predef == 4 ? "Win64" : "all"); 755 tokIt.text = "version(" ~ ver ~ ") /* " ~ tokIt.text; 756 lastIt.text ~= " */ {"; 757 elif_braces = "} "; 758 } 759 else 760 { 761 version(static_if_to_version) 762 { 763 string cond = pp; 764 version(remove_pp) 765 if(pp == "pp_ifndef") 766 cond = "all"; 767 768 tokIt.text = "version(" ~ cond ~ ") /* " ~ tokIt.text; 769 lastIt.text ~= " */ {"; 770 } 771 else 772 { 773 tokIt.text = "static if(" ~ pp ~ "(r\""; 774 tokIt[1].pretext = ""; 775 lastIt.text ~= "\")) {"; 776 } 777 elif_braces = "} "; 778 } 779 780 if(pp == "pp_elif") 781 { 782 tokIt.text = elif_braces_stack[$-1] ~ "else " ~ tokIt.text; 783 elif_braces_stack[$-1] = elif_braces; 784 } 785 else 786 { 787 elif_braces_stack ~= elif_braces; 788 pp_enable_stack ~= true; 789 } 790 791 } 792 793 bool inDisabledPPBranch() 794 { 795 foreach (string s; elif_braces_stack) 796 if(startsWith(s, "+/")) 797 return true; 798 return false; 799 } 800 801 string convertPP(string text, int lineno, bool inEnum) 802 { 803 version(remove_pp) {} else 804 if(inEnum) 805 return "// " ~ text; 806 807 TokenList tokens = scanText(text, lineno, false); 808 TokenIterator tokIt = tokens.begin(); 809 TokenIterator lastIt = tokens.end() - 1; 810 if(lastIt.type == Token.EOF) 811 --lastIt; 812 813 switch(tokIt.text) 814 { 815 case "#include": 816 tokIt.text = "public import"; 817 if(tokIt[1].type == Token.String) 818 tokIt[1].text = fixImport(tokIt[1].text) ~ ";"; 819 else if(tokIt[1].text == "<") 820 { 821 string inc; 822 TokenIterator it = tokIt + 2; 823 for( ; !it.atEnd() && it.text != ">"; it.erase()) 824 inc ~= it.pretext ~ it.text; 825 826 tokIt[1].text = fixImport(inc); 827 if(!it.atEnd()) 828 it.text = ";"; 829 } 830 break; 831 case "#if": 832 handleCondition(tokIt, lastIt, "pp_if"); 833 break; 834 case "#ifndef": 835 handleCondition(tokIt, lastIt, "pp_ifndef"); 836 break; 837 case "#ifdef": 838 handleCondition(tokIt, lastIt, "pp_ifdef"); 839 break; 840 case "#endif": 841 if(pp_enable_stack.length == 0) 842 throwException(tokIt.lineno, "unbalanced #endif"); 843 bool enabled = pp_enable_stack[$-1]; 844 pp_enable_stack = pp_enable_stack[0 .. $-1]; 845 if(!enabled) 846 tokIt.pretext = "+/" ~ tokIt.pretext; 847 version(remove_pp) 848 tokIt.text = elif_braces_stack[$-1] ~ "\n"; 849 else 850 tokIt.text = elif_braces_stack[$-1] ~ "// " ~ tokIt.text; 851 elif_braces_stack = elif_braces_stack[0 .. $-1]; 852 break; 853 case "#else": 854 if(pp_enable_stack.length == 0) 855 throwException(tokIt.lineno, "unbalanced #else"); 856 if(!pp_enable_stack[$-1]) 857 { 858 tokIt.pretext = "+/" ~ tokIt.pretext; 859 pp_enable_stack[$-1] = true; 860 } 861 if(elif_braces_stack[$-1].startsWith("+/")) 862 { 863 version(remove_pp) 864 tokIt.text = "+/} else {\n"; 865 else 866 tokIt.text = "+/} else { // " ~ tokIt.text; 867 elif_braces_stack[$-1] = elif_braces_stack[$-1][2..$]; 868 } 869 else 870 { 871 version(remove_pp) 872 tokIt.text = "} else {\n"; 873 else 874 tokIt.text = "} else { // " ~ tokIt.text; 875 } 876 break; 877 case "#elif": 878 if(pp_enable_stack.length == 0) 879 throwException(tokIt.lineno, "unbalanced #elif"); 880 if(!pp_enable_stack[$-1]) 881 { 882 tokIt.pretext = "+/" ~ tokIt.pretext; 883 pp_enable_stack[$-1] = true; 884 } 885 handleCondition(tokIt, lastIt, "pp_elif"); 886 //tokIt[1].pretext = ""; 887 //lastIt.text ~= "\")) {"; 888 break; 889 case "#define": 890 convertDefine(tokIt); 891 break; 892 default: 893 return "// " ~ text; 894 } 895 string txt = tokenListToString(tokens); 896 return txt; 897 } 898 899 bool convertDefine(ref TokenIterator tokIt) 900 { 901 // tokIt on "#define" 902 bool convert = true; 903 bool predef = false; 904 bool convertMacro = false; 905 string argtype; 906 string rettype; 907 TokenIterator it = tokIt + 1; 908 909 string ident = it.text; 910 for( ; !it.atEnd(); ++it) {} 911 version(none){ 912 if(indexOf(it.pretext, "\\\n") >= 0) 913 { 914 convert = false; 915 it.pretext = replace(it.pretext, "\\\n", "\\\n//"); 916 } 917 // if(indexOf(it.pretext, '\n') >= 0) 918 // break; 919 } 920 921 TokenIterator endIt = it; 922 if(it[-1].type == Token.EOF) 923 --endIt; 924 925 int preDefType = preDefined(ident); 926 if(ident in disabled_defines) 927 predef = true; 928 else if (preDefType == 3) 929 { 930 predef = true; 931 convert = false; 932 } 933 else if (preDefType == 1 || preDefined("_" ~ ident ~ "_DEFINED") == 1) 934 predef = true; 935 else if(tokIt[2].text == "(" && tokIt[2].pretext.length == 0) 936 { 937 convert = false; 938 if(tokIt[3].text == ")") 939 { 940 convertMacro = hasBalancedBrackets(tokIt + 4, endIt); 941 argtype = ""; 942 if(isExpression(tokIt + 4, endIt)) 943 rettype = getExpressionType(ident, tokIt + 4, endIt); 944 else 945 rettype = "void"; 946 } 947 if(tokIt[3].type == Token.Identifier && tokIt[4].text == ")" && isExpression(tokIt + 5, endIt)) 948 { 949 convertMacro = true; 950 rettype = getExpressionType(ident, tokIt + 5, endIt); 951 argtype = getArgumentType(ident, tokIt + 5, endIt, rettype); 952 } 953 } 954 else if(ident.startsWith("CF_VS")) 955 { 956 convertMacro = true; 957 rettype = "UINT"; 958 } 959 else if(!isExpression(tokIt + 2, endIt)) 960 convert = false; 961 else if(string* m = ident in converted_defines) 962 if(*m != currentModule) 963 predef = true; 964 965 if((!convert && !convertMacro) || it[-1].text == "\\" || predef) 966 { 967 tokIt.pretext ~= "// "; 968 convert = false; 969 } 970 971 if(convertMacro) 972 { 973 TokenIterator lastit = endIt; 974 version(macro2template) tokIt.text = "auto"; 975 else tokIt.text = rettype; 976 string ret = (rettype != "void" ? "return " : ""); 977 if(argtype.length) 978 { 979 version(macro2template) tokIt[3].pretext ~= "ARG)(ARG "; 980 else tokIt[3].pretext ~= argtype ~ " "; 981 tokIt[5].pretext ~= "{ " ~ ret; 982 lastit = tokIt + 5; 983 } 984 else if(tokIt[2].text != "(" || tokIt[2].pretext != "") 985 { 986 tokIt[2].pretext = "() { " ~ ret ~ tokIt[2].pretext; 987 lastit = tokIt + 2; 988 } 989 else 990 { 991 tokIt[4].pretext = " { " ~ ret ~ tokIt[4].pretext; 992 lastit = tokIt + 4; 993 } 994 995 if(lastit == endIt) // empty? 996 endIt.text ~= " }"; 997 else 998 endIt[-1].text ~= "; }"; 999 1000 if(!inDisabledPPBranch()) 1001 converted_defines[ident] = currentModule; 1002 } 1003 else if(convert) 1004 { 1005 if(it != tokIt + 1 && it != tokIt + 2 && it != tokIt + 3) 1006 { 1007 if(endIt == tokIt + 3 && tokIt[2].type == Token.Identifier && 1008 !(tokIt[2].text in enums) && tokIt[2].text != "NULL") 1009 { 1010 if(tokIt[2].text in disabled_defines) 1011 tokIt.pretext ~= "// "; 1012 tokIt.text = "alias"; 1013 tokIt[1].text = tokIt[2].text; 1014 tokIt[2].text = ident; 1015 } 1016 else 1017 { 1018 tokIt.text = "denum"; 1019 (tokIt+2).insertBefore(createToken(" ", "=", Token.Assign, tokIt.lineno)); 1020 if(ident.startsWith("uuid_")) 1021 { 1022 tokIt.insertAfter(createToken(" ", "GUID", Token.Identifier, tokIt.lineno)); 1023 tokIt[4].pretext ~= "uuid(\""; 1024 endIt[-1].text ~= "\")"; 1025 } 1026 else if(ident.startsWith("SID_S") || ident.startsWith("guid")) 1027 { 1028 tokIt.insertAfter(createToken(" ", "GUID", Token.Identifier, tokIt.lineno)); 1029 } 1030 // winnt.h 1031 else if(ident.startsWith("SECURITY_") && tokIt[3].text == "{" && tokIt[15].text == "}") 1032 { 1033 tokIt.insertAfter(createToken(" ", "SID_IDENTIFIER_AUTHORITY", Token.Identifier, tokIt.lineno)); 1034 tokIt[4].text = "{["; 1035 tokIt[16].text = "]}"; 1036 } 1037 else if(_endsWith(ident, "_LUID") && tokIt[3].text == "{") 1038 { 1039 tokIt.insertAfter(createToken(" ", "LUID", Token.Identifier, tokIt.lineno)); 1040 } 1041 } 1042 } 1043 else 1044 tokIt.pretext ~= "// "; 1045 1046 Token tok = createToken("", ";", Token.Comma, tokIt.lineno); 1047 endIt.insertBefore(tok); 1048 if(!inDisabledPPBranch()) 1049 converted_defines[ident] = currentModule; 1050 } 1051 else if (!predef) 1052 disabled_defines[ident] = 1; 1053 1054 string repl = (convert || convertMacro ? "\n" : "\\\n//"); 1055 for(it = tokIt; !it.atEnd(); ++it) 1056 if(indexOf(it.pretext, "\\\n") >= 0) 1057 it.pretext = replace(it.pretext, "\\\n", repl); 1058 1059 tokIt = it - 1; 1060 return convert || convertMacro; 1061 } 1062 1063 void disable_macro(ref TokenIterator tokIt) 1064 { 1065 TokenIterator it = tokIt + 1; 1066 if(it.text == "(") 1067 { 1068 if(!advanceToClosingBracket(it)) 1069 return; 1070 } 1071 version(all) 1072 { 1073 tokIt.insertBefore(createToken("", "/", Token.Div, tokIt.lineno)); 1074 tokIt.insertBefore(createToken("", "+", Token.Plus, tokIt.lineno)); 1075 tokIt[-2].pretext = tokIt.pretext; 1076 tokIt.pretext = " "; 1077 it.insertBefore(createToken(" ", "+", Token.Plus, tokIt.lineno)); 1078 it.insertBefore(createToken("", "/", Token.Div, tokIt.lineno)); 1079 tokIt = it - 1; 1080 } else { 1081 tokIt.pretext ~= "/+"; 1082 it[-1].text ~= "+/"; // it.pretext = "+/" ~ it.pretext; 1083 tokIt = it - 1; 1084 } 1085 } 1086 1087 void replaceExpressionTokens(TokenList tokens) 1088 { 1089 //replaceTokenSequence(tokens, "= (", "= cast(", true); 1090 replaceTokenSequence(tokens, "$_not $_ident($_ident1)$_ident2", "$_not cast($_ident1)$_ident2", true); 1091 replaceTokenSequence(tokens, "$_not $_ident($_ident1)$_num2", "$_not cast($_ident1)$_num2", true); 1092 replaceTokenSequence(tokens, "$_not $_ident($_ident1)-$_num2", "$_not cast($_ident1)-$_num2", true); 1093 replaceTokenSequence(tokens, "$_not $_ident($_ident1)~", "$_not cast($_ident1)~", true); 1094 while(replaceTokenSequence(tokens, "$_not $_ident($_ident1)($expr)", "$_not cast($_ident1)($expr)", true) > 0) {} 1095 replaceTokenSequence(tokens, "$_not $_ident($_ident1)cast", "$_not cast($_ident1)cast", true); 1096 replaceTokenSequence(tokens, "$_not $_ident($_ident1*)$_not_semi;", "$_not cast($_ident1*)$_not_semi", true); 1097 replaceTokenSequence(tokens, "$_not $_ident(struct $_ident1*)$_not_semi;", "$_not cast(struct $_ident1*)$_not_semi", true); 1098 replaceTokenSequence(tokens, "$_not $_ident($_ident1 $_ident2*)", "$_not cast($_ident1 $_ident2*)", true); 1099 replaceTokenSequence(tokens, "HRESULT cast", "HRESULT", true); 1100 replaceTokenSequence(tokens, "extern cast", "extern", true); 1101 replaceTokenSequence(tokens, "!cast", "!", true); 1102 replaceTokenSequence(tokens, "reinterpret_cast<$_ident>", "cast($_ident)", true); 1103 replaceTokenSequence(tokens, "reinterpret_cast<$_ident*>", "cast($_ident*)", true); 1104 replaceTokenSequence(tokens, "const_cast<$_ident*>", "cast($_ident*)", true); 1105 } 1106 1107 string translateModuleName(string name) 1108 { 1109 name = toLower(name); 1110 if(name == "version" || name == "shared" || name == "align") 1111 return keywordPrefix ~ name; 1112 return name; 1113 } 1114 1115 string translatePackageName(string fname) 1116 { 1117 // "shared", "um" added in SDK 8.0, "um\minwin" in 10.0.10586.0 1118 return fname.replace("\\shared\\", "\\").replace("\\um\\", "\\").replace("\\minwin\\", "\\"); 1119 } 1120 1121 string translateFilename(string fname) 1122 { 1123 string name = getNameWithoutExt(fname); 1124 string nname = translateModuleName(name); 1125 if(name == nname) 1126 return translatePackageName(fname); 1127 1128 string dir = dirName(fname); 1129 if(dir == ".") 1130 dir = ""; 1131 else 1132 dir ~= "\\"; 1133 string ext = extension(fname); 1134 return translatePackageName(dir ~ nname ~ ext); 1135 } 1136 1137 string _fixImport(string text) 1138 { 1139 text = replace(text, "/", "\\"); 1140 text = replace(text, "\"", ""); 1141 text = toLower(getNameWithoutExt(text)); 1142 string ntext = translateFilename(text); 1143 string name = translateModuleName(text); 1144 foreach(string file; srcfiles) 1145 { 1146 if(translateModuleName(getNameWithoutExt(file)) == name) 1147 { 1148 if(file.startsWith(win_path)) 1149 return packageWin ~ ntext; 1150 else 1151 return packageVSI ~ ntext; 1152 } 1153 } 1154 return packageNF ~ ntext; 1155 } 1156 1157 string fixImport(string text) 1158 { 1159 string imp = _fixImport(text); 1160 currentImports.addunique(imp); 1161 return imp; 1162 } 1163 1164 void convertGUID(TokenIterator tokIt) 1165 { 1166 // tokIt after "{" 1167 static bool numberOrIdent(Token tok) 1168 { 1169 return tok.type == Token.Identifier || tok.type == Token.Number; 1170 } 1171 static string toByteArray(string txt) 1172 { 1173 string ntxt; 1174 for(int i = 0; i + 1 < txt.length; i += 2) 1175 { 1176 if(i > 0) 1177 ntxt ~= ","; 1178 ntxt ~= "0x" ~ txt[i .. i + 2]; 1179 } 1180 return ntxt; 1181 } 1182 1183 if (numberOrIdent(tokIt[0]) && tokIt[1].text == "-" && 1184 numberOrIdent(tokIt[2]) && tokIt[3].text == "-" && 1185 numberOrIdent(tokIt[4]) && tokIt[5].text == "-" && 1186 numberOrIdent(tokIt[6]) && tokIt[7].text == "-" && 1187 numberOrIdent(tokIt[8]) && tokIt[9].text == "}" && 1188 tokIt[8].text.length == 12) 1189 { 1190 // 00020405-0000-0000-C000-000000000046 1191 tokIt[0].text = "0x" ~ tokIt[0].text; tokIt[1].text = ","; 1192 tokIt[2].text = "0x" ~ tokIt[2].text; tokIt[3].text = ","; 1193 tokIt[4].text = "0x" ~ tokIt[4].text; tokIt[5].text = ","; 1194 1195 tokIt[6].text = "[ " ~ toByteArray(tokIt[6].text); tokIt[7].text = ","; 1196 tokIt[8].text = toByteArray(tokIt[8].text) ~ " ]"; 1197 } 1198 else if (tokIt[0].type == Token.Identifier && tokIt[1].text == "}") 1199 { 1200 // simple identifer defined elsewhere 1201 tokIt[-1].text = ""; 1202 tokIt[1].text = ""; 1203 } 1204 else if (tokIt[0].type == Token.Number && tokIt[1].text == "," && 1205 tokIt[2].type == Token.Number && tokIt[3].text == "," && 1206 tokIt[4].type == Token.Number && tokIt[5].text == ",") 1207 { 1208 // 0x0c539790, 0x12e4, 0x11cf, 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8 1209 if(tokIt[6].text == "{") 1210 { 1211 tokIt[6].pretext ~= "["; // use pretext to avoid later substitution 1212 tokIt[6].text = ""; 1213 tokIt[22].pretext ~= "]"; 1214 tokIt[22].text = ""; 1215 } 1216 else if(tokIt[6].text != "[") 1217 { 1218 int i; 1219 for(i = 0; i < 8; i++) 1220 if(tokIt[5 + 2*i].text != "," || tokIt[6 + 2*i].type != Token.Number) 1221 break; 1222 if (i >= 8) 1223 { 1224 tokIt[6].pretext = " [" ~ tokIt[6].pretext; 1225 tokIt[21].pretext = " ]" ~ tokIt[21].pretext; 1226 } 1227 } 1228 } 1229 else if(tokIt.type == Token.String) 1230 { 1231 string txt = tokIt.text; 1232 // "af855397-c4dc-478b-abd4-c3dbb3759e72" 1233 if(txt.length == 38 && txt[9] == '-' && txt[14] == '-' && txt[19] == '-' && txt[24] == '-') 1234 { 1235 tokIt.text = "0x" ~ txt[1..9] ~ ", 0x" ~ txt[10..14] ~ ", 0x" ~ txt[15..19] ~ ", [ " 1236 ~ "0x" ~ txt[20..22] ~ ", 0x" ~ txt[22..24]; 1237 for(int i = 0; i < 6; i++) 1238 tokIt.text ~= ", 0x" ~ txt[25 + 2*i .. 27 + 2*i]; 1239 tokIt.text ~= " ]"; 1240 } 1241 } 1242 else 1243 { 1244 tokIt.pretext ~= "\""; 1245 while(tokIt.text != "}") 1246 { 1247 ++tokIt; 1248 if(tokIt.atEnd()) 1249 return; 1250 } 1251 tokIt.pretext = "\"" ~ tokIt.pretext; 1252 } 1253 } 1254 1255 string convertText(TokenList tokens) 1256 { 1257 string prevtext; 1258 1259 int braceCount; 1260 int parenCount; 1261 int brackCount; 1262 int enumLevel = -1; 1263 1264 //replaceTokenSequence(tokens, "enum Kind { $enums ;", "class Kind { /+ $enums; +/", false); 1265 1266 // do some preprocessor replacements to make the text bracket-balanced 1267 if(currentModule == "oaidl") 1268 { 1269 replaceTokenSequence(tokens, "__VARIANT_NAME_1", "", true); 1270 replaceTokenSequence(tokens, "__VARIANT_NAME_2", "", true); 1271 replaceTokenSequence(tokens, "__VARIANT_NAME_3", "", true); 1272 replaceTokenSequence(tokens, "__VARIANT_NAME_4", "", true); 1273 } 1274 1275 if(currentModule == "windef") 1276 { 1277 // avoid removal of #define TRUE 1 1278 replaceTokenSequence(tokens, "#ifndef TRUE\n#define TRUE$def\n#endif\n", "#define TRUE 1\n", false); 1279 } 1280 1281 if(currentModule == "winnt") 1282 { 1283 replaceTokenSequence(tokens, "#if defined(MIDL_PASS)\ntypedef struct $_ident {\n" 1284 ~ "#else$comment_else\n$else\n#endif$comment_endif", "$else", false); 1285 // remove int64 operations 1286 replaceTokenSequence(tokens, "#if defined(MIDL_PASS)$if_more\n#define Int32x32To64$def_more\n$defines\n" 1287 ~ "#error Must define a target architecture.\n#endif\n", "/+\n$*\n+/", false); 1288 // remove rotate operations 1289 replaceTokenSequence(tokens, "#define RotateLeft8$def_more\n$defines\n" 1290 ~ "#pragma intrinsic(_rotr16)\n", "/+\n$*\n+/", false); 1291 1292 replaceTokenSequence(tokens, "typedef struct DECLSPEC_ALIGN($_num)", "align($_num) typedef struct", true); 1293 replaceTokenSequence(tokens, "typedef union DECLSPEC_ALIGN($_num)", "align($_num) typedef union", true); 1294 replaceTokenSequence(tokens, "struct DECLSPEC_ALIGN($_num)", "align($_num) struct", true); 1295 1296 // win 8.1: remove template _ENUM_FLAG_INTEGER_FOR_SIZE 1297 replaceTokenSequence(tokens, "template $args _ENUM_FLAG_INTEGER_FOR_SIZE;", "/*$0*/", true); 1298 replaceTokenSequence(tokens, "template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE <$arg> { $def };", "/*$0*/", true); 1299 replaceTokenSequence(tokens, "template <$arg> struct _ENUM_FLAG_SIZED_INTEGER { $def };", "/*$0*/", true); 1300 1301 // win 10.0.17134.0: typedef enum MEM_EXTENDED_PARAMETER_TYPE {} MEM_EXTENDED_PARAMETER_TYPE, ... 1302 replaceTokenSequence(tokens, "MEM_EXTENDED_PARAMETER_TYPE, *PMEM_EXTENDED_PARAMETER_TYPE", "*PMEM_EXTENDED_PARAMETER_TYPE", true); 1303 // win 10.0.17763.0: typedef enum MEM_SECTION_EXTENDED_PARAMETER_TYPE {} MEM_SECTION_EXTENDED_PARAMETER_TYPE, ... 1304 replaceTokenSequence(tokens, "MEM_SECTION_EXTENDED_PARAMETER_TYPE, *PMEM_SECTION_EXTENDED_PARAMETER_TYPE", "*PMEM_SECTION_EXTENDED_PARAMETER_TYPE", true); 1305 // win 10.0.18362.0: typedef struct DECLSPEC_ALIGN(16) DECLSPEC_NOINITALL _CONTEXT ... 1306 replaceTokenSequence(tokens, "DECLSPEC_NOINITALL", "", true); 1307 1308 replaceTokenSequence(tokens, "RtlZeroMemory($dest,$length)", 1309 "import core.stdc.string: memset; memset($dest,0,$length)", true); 1310 } 1311 1312 if(currentModule == "commctrl") 1313 { 1314 // typos 1315 replaceTokenSequence(tokens, "PCCOMBOEXITEMW", "PCCOMBOBOXEXITEMW", true); 1316 replaceTokenSequence(tokens, "LPTBSAVEPARAMW", "LPTBSAVEPARAMSW", true); 1317 } 1318 if(currentModule == "oleauto") 1319 { 1320 replaceTokenSequence(tokens, "WINOLEAUTAPI_($_rettype)", "extern(Windows) $_rettype", true); 1321 replaceTokenSequence(tokens, "WINOLEAUTAPI", "extern(Windows) HRESULT", true); 1322 // rename the three argument inlined overload, LDC stumbles over it 1323 replaceTokenSequence(tokens, "VarCmp($arg1, $arg2, $arg3) { $code$ }", 1324 "VarCmp_inl($arg1, $arg2, $arg3) { $code$ }", true); 1325 } 1326 if(currentModule == "shellapi") 1327 { 1328 replaceTokenSequence(tokens, "SHSTDAPI_($_rettype)", "extern(Windows) $_rettype", true); 1329 replaceTokenSequence(tokens, "SHSTDAPI", "extern(Windows) HRESULT", true); 1330 replaceTokenSequence(tokens, "LWSTDAPIV_($_rettype)", "extern(Windows) $_rettype", true); 1331 } 1332 replaceTokenSequence(tokens, "STDAPI_($_rettype)", "extern(Windows) $_rettype", true); 1333 replaceTokenSequence(tokens, "STDAPI", "extern(Windows) HRESULT", true); 1334 replaceTokenSequence(tokens, "STDMETHODCALLTYPE", "extern(Windows)", true); 1335 replaceTokenSequence(tokens, "STDAPICALLTYPE", "extern(Windows)", true); 1336 replaceTokenSequence(tokens, "WINOLEAPI_($_rettype)", "extern(Windows) $_rettype", true); 1337 replaceTokenSequence(tokens, "WINOLEAPI", "extern(Windows) HRESULT", true); 1338 replaceTokenSequence(tokens, "$_ident WINAPIV", "extern(C) $_ident", true); 1339 1340 replaceTokenSequence(tokens, "RPCRTAPI", "export", true); 1341 replaceTokenSequence(tokens, "RPC_STATUS", "int", true); 1342 replaceTokenSequence(tokens, "RPC_ENTRY", "extern(Windows)", true); 1343 replaceTokenSequence(tokens, "__RPC_USER", "extern(Windows)", true); 1344 replaceTokenSequence(tokens, "__RPC_STUB", "extern(Windows)", true); 1345 replaceTokenSequence(tokens, "__RPC_API", "extern(Windows)", true); 1346 replaceTokenSequence(tokens, "RPC_MGR_EPV", "void", true); 1347 replaceTokenSequence(tokens, "__RPC_FAR", "", true); 1348 replaceTokenSequence(tokens, "POINTER_32", "", true); 1349 replaceTokenSequence(tokens, "POINTER_64", "", true); 1350 replaceTokenSequence(tokens, "UNREFERENCED_PARAMETER($arg);", "/*UNREFERENCED_PARAMETER($arg);*/", true); 1351 if(currentModule == "rpcdce") 1352 { 1353 replaceTokenSequence(tokens, "RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN($args);", 1354 "function($args) RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN;", true); 1355 } 1356 // windef.h and ktmtypes.h 1357 replaceTokenSequence(tokens, "UOW UOW;", "UOW uow;", true); 1358 1359 // enc.idl (FIELD_OFFSET already defined in winnt.h) 1360 replaceTokenSequence(tokens, "typedef struct _FIELD_OFFSET { $data } FIELD_OFFSET;", 1361 "struct _FIELD_OFFSET { $data };", true); 1362 1363 // IP_DEST_PORT_UNREACHABLE defined twice 1364 if(currentModule == "ipexport") 1365 { 1366 replaceTokenSequence(tokens, "#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)\n" ~ 1367 "#define IP_HOP_LIMIT_EXCEEDED (IP_STATUS_BASE + 13)\n", 1368 "#define IP_HOP_LIMIT_EXCEEDED (IP_STATUS_BASE + 13)\n", false); 1369 } 1370 if(currentModule == "nldef") 1371 { 1372 // expand MAKE_ROUTE_PROTOCOL 1373 replaceTokenSequence(tokens, "MAKE_ROUTE_PROTOCOL($_ident,$_num),", 1374 "MIB_IPPROTO_ __ $_ident = $_num, PROTO_IP_ __ $_ident = $_num,", true); 1375 } 1376 if(currentModule == "iphlpapi") 1377 { 1378 // imports inside extern(C) {} 1379 replaceTokenSequence(tokens, "extern \"C\" { $_data }", "$_data", true); 1380 } 1381 if(currentModule == "fileapifromapp") 1382 { 1383 replaceTokenSequence(tokens, "WINSTORAGEAPI", "", true); 1384 } 1385 if(currentModule == "propidlbase") 1386 { 1387 replaceTokenSequence(tokens, "_VARIANT_BOOL bool;", "/*_VARIANT_BOOL bool;*/", true); 1388 replaceTokenSequence(tokens, "TYPEDEF_CA($_identType,$_identName);", 1389 "struct $_identName { ULONG cElems; $_identType* pElems; };", true); 1390 } 1391 if(currentModule == "imageparameters140") 1392 { 1393 // type name and field name identical 1394 replaceTokenSequence(tokens, "ImageMoniker ImageMoniker;", "ImageMoniker mImageMoniker;", true); 1395 } 1396 1397 // select unicode version of the API when defining without postfix A/W 1398 replaceTokenSequence(tokens, "#ifdef UNICODE\nreturn $_identW(\n#else\nreturn $_identA(\n#endif\n", 1399 " return $_identW(", false); 1400 1401 replaceTokenSequence(tokens, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false); 1402 replaceTokenSequence(tokens, "#ifdef defined(__cplusplus)\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false); 1403 replaceTokenSequence(tokens, "#ifdef defined __cplusplus\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false); 1404 replaceTokenSequence(tokens, "#ifdef __cplusplus\n}\n#endif\n", "}\n", false); 1405 1406 if(currentModule == "vsshell160") 1407 { 1408 replaceTokenSequence(tokens, "#ifndef INTEROPLIB\n[in] $ifcode\n#else\n$elsecode\n#endif", "[in] $ifcode", false); 1409 } 1410 1411 for(TokenIterator tokIt = tokens.begin(); tokIt != tokens.end; ) 1412 { 1413 Token tok = *tokIt; 1414 1415 switch(tok.text) 1416 { 1417 case "(": 1418 parenCount++; 1419 break; 1420 case ")": 1421 parenCount--; 1422 break; 1423 case "[": 1424 brackCount++; 1425 break; 1426 case "]": 1427 brackCount--; 1428 break; 1429 case "{": 1430 braceCount++; 1431 break; 1432 case "}": 1433 braceCount--; 1434 if(braceCount <= enumLevel) 1435 enumLevel = -1; 1436 break; 1437 1438 case "enum": 1439 enumLevel = braceCount; 1440 break; 1441 case ";": 1442 enumLevel = -1; 1443 break; 1444 1445 case "importlib": 1446 if(tokIt[1].text == "(" && tokIt[2].type == Token.String && tokIt[3].text == ")") 1447 { 1448 tokIt.text = "import"; 1449 tokIt[1].text = ""; 1450 tokIt[2].pretext = " "; 1451 tokIt[2].text = fixImport(tokIt[2].text); 1452 tokIt[3].text = ""; 1453 } 1454 break; 1455 case "import": 1456 if(tokIt[1].type == Token.String) 1457 { 1458 tokIt.pretext ~= "public "; 1459 tokIt[1].text = fixImport(tokIt[1].text); 1460 } 1461 break; 1462 1463 case "midl_pragma": 1464 comment_line(tokIt); 1465 continue; 1466 1467 case "cpp_quote": 1468 //reinsert_cpp_quote(tokIt); 1469 if(handle_cpp_quote(tokIt, enumLevel >= 0)) 1470 continue; 1471 break; 1472 1473 case "version": 1474 case "align": 1475 case "package": 1476 case "function": 1477 if(tokIt[1].text != "(") 1478 tok.text = keywordPrefix ~ tok.text; 1479 break; 1480 1481 case "unsigned": 1482 { 1483 string t; 1484 bool skipNext = true; 1485 switch(tokIt[1].text) 1486 { 1487 case "__int64": t = "ulong"; break; 1488 case "long": t = "uint"; break; 1489 case "int": t = "uint"; break; 1490 case "__int32": t = "uint"; break; 1491 case "__int3264": t = "uint"; break; 1492 case "short": t = "ushort"; break; 1493 case "char": t = "ubyte"; break; 1494 default: 1495 t = "uint"; 1496 skipNext = false; 1497 break; 1498 } 1499 tok.text = t; 1500 if(skipNext) 1501 (tokIt + 1).erase(); 1502 break; 1503 } 1504 case "signed": 1505 { 1506 string t; 1507 bool skipNext = true; 1508 switch(tokIt[1].text) 1509 { 1510 case "__int64": t = "long"; break; 1511 case "long": t = "int"; break; 1512 case "int": t = "int"; break; 1513 case "__int32": t = "int"; break; 1514 case "__int3264": t = "int"; break; 1515 case "short": t = "short"; break; 1516 case "char": t = "byte"; break; 1517 default: 1518 t = "int"; 1519 skipNext = false; 1520 break; 1521 } 1522 tok.text = t; 1523 if(skipNext) 1524 (tokIt + 1).erase(); 1525 break; 1526 } 1527 // Windows SDK 8.0 => 7.1 1528 case "_Null_terminated_": tok.text = "__nullterminated"; break; 1529 case "_NullNull_terminated_": tok.text = "__nullnullterminated"; break; 1530 case "_Success_": tok.text = "__success"; break; 1531 case "_In_": tok.text = "__in"; break; 1532 case "_Inout_": tok.text = "__inout"; break; 1533 case "_In_opt_": tok.text = "__in_opt"; break; 1534 case "_Inout_opt_": tok.text = "__inout_opt"; break; 1535 case "_Inout_z_": tok.text = "__inout_z"; break; 1536 case "_Deref_out_": tok.text = "__deref_out"; break; 1537 case "_Out_": tok.text = "__out"; break; 1538 case "_Out_opt_": tok.text = "__out_opt"; break; 1539 case "_Field_range_": tok.text = "__range"; break; 1540 case "_Field_size_": tok.text = "__field_ecount"; break; 1541 case "_Field_size_opt_": tok.text = "__field_ecount_opt"; break; 1542 case "_Field_size_bytes_": tok.text = "__field_bcount"; break; 1543 case "_Field_size_bytes_opt_":tok.text = "__field_bcount_opt"; break; 1544 1545 default: 1546 if(tok.type == Token.Macro && tok.text.startsWith("$")) 1547 tok.text = "_d_" ~ tok.text[1..$]; 1548 else if(tok.type == Token.Number && (tok.text._endsWith("l") || tok.text._endsWith("L"))) 1549 tok.text = tok.text[0..$-1]; 1550 else if(tok.type == Token.Number && tok.text._endsWith("i64")) 1551 tok.text = tok.text[0..$-3] ~ "L"; 1552 else if(tok.type == Token.Number && tok.text._endsWith("UI64")) 1553 tok.text = tok.text[0..$-4] ~ "UL"; 1554 else if(tok.type == Token.String && tok.text.startsWith("L\"")) 1555 tok.text = tok.text[1..$] ~ "w.ptr"; 1556 else if(tok.type == Token.String && tok.text.startsWith("L\'")) 1557 tok.text = tok.text[1..$]; 1558 else if(tok.text.startsWith("#")) 1559 { 1560 string txt = convertPP(tok.text, tok.lineno, enumLevel >= 0); 1561 reinsertTextTokens(tokIt, txt); 1562 continue; 1563 } 1564 else if(tok.text in disabled_defines) 1565 disable_macro(tokIt); 1566 else if(parenCount > 0) 1567 { 1568 // in function argument 1569 //if(tok.text == "const" || tok.text == "CONST") 1570 // tok.text = "/*const*/"; 1571 //else 1572 if (tok.text.startsWith("REF") && 1573 tok.text != "REFSHOWFLAGS" && !tok.text.startsWith("REFERENCE")) 1574 { 1575 tokIt.insertBefore(createToken(tok.pretext, "ref", Token.Identifier, tokIt.lineno)); 1576 tok.pretext = " "; 1577 tok.text = tok.text[3..$]; 1578 } 1579 } 1580 else if(tok.type == Token.Identifier && enumLevel >= 0 && (tokIt[-1].text == "{" || tokIt[-1].text == ",")) 1581 enums[tok.text] = true; 1582 break; 1583 } 1584 prevtext = tok.text; 1585 ++tokIt; 1586 } 1587 1588 version(none) version(vsi) 1589 { 1590 // wtypes.idl: 1591 replaceTokenSequence(tokens, "typedef ubyte UCHAR;", "typedef ubyte idl_UCHAR;", true); 1592 replaceTokenSequence(tokens, "typedef short SHORT;", "typedef short idl_SHORT;", true); 1593 replaceTokenSequence(tokens, "typedef ushort USHORT;", "typedef ushort idl_USHORT;", true); 1594 replaceTokenSequence(tokens, "typedef DWORD ULONG;", "typedef DWORD idl_ULONG;", true); 1595 replaceTokenSequence(tokens, "typedef double DOUBLE;", "typedef double idl_DOUBLE;", true); 1596 replaceTokenSequence(tokens, "typedef char OLECHAR;", "typedef char idl_OLECHAR;", true); 1597 replaceTokenSequence(tokens, "typedef LPSTR LPOLESTR;", "typedef LPSTR idl_LPOLESTR;", true); 1598 replaceTokenSequence(tokens, "typedef LPCSTR LPCOLESTR;", "typedef LPCSTR idl_LPCOLESTR;", true); 1599 1600 replaceTokenSequence(tokens, "WCHAR OLECHAR;", "WCHAR idl_OLECHAR;", true); 1601 replaceTokenSequence(tokens, "OLECHAR *LPOLESTR;", "OLECHAR *idl_LPOLESTR;", true); 1602 replaceTokenSequence(tokens, "const OLECHAR *LPCOLESTR;", "OLECHAR *idl_LPCOLESTR;", true); 1603 1604 replaceTokenSequence(tokens, "typedef LONG SCODE;", "typedef LONG vsi_SCODE;", true); 1605 } 1606 1607 //replaceTokenSequence(tokens, "interface IWinTypes { $data }", 1608 // "/+interface IWinTypes {+/\n$data\n/+ } /+IWinTypes+/ +/", true); 1609 1610 // docobj.idl (v6.0a) 1611 if(currentModule == "docobj") 1612 { 1613 replaceTokenSequence(tokens, "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000, OLECMDIDF_REFRESH_THROUGHSCRIPT = 0x4000 $_not,", 1614 "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000,\nOLECMDIDF_REFRESH_THROUGHSCRIPT = 0x4000, $_not", true); 1615 replaceTokenSequence(tokens, "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000 $_not,", "OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000, $_not", true); 1616 1617 // win SDK 8.1: double define 1618 replaceTokenSequence(tokens, "typedef struct tagPAGESET {} PAGESET;", "", true); 1619 } 1620 1621 //vsshell.idl 1622 if(currentModule == "vsshell") 1623 { 1624 replaceTokenSequence(tokens, "typedef DWORD PFN_TSHELL_TMP;", "typedef PfnTshell PFN_TSHELL_TMP;", true); 1625 replaceTokenSequence(tokens, "MENUEDITOR_TRANSACTION_ALL,", "MENUEDITOR_TRANSACTION_ALL = 0,", true); 1626 replaceTokenSequence(tokens, "SCC_STATUS_INVALID = -1L,", "SCC_STATUS_INVALID = cast(DWORD)-1L,", true); 1627 } 1628 if(currentModule == "vsshell80") 1629 { 1630 replaceTokenSequence(tokens, "MENUEDITOR_TRANSACTION_ALL,", "MENUEDITOR_TRANSACTION_ALL = 0,", true); // overflow from -1u 1631 } 1632 1633 // vslangproj90.idl 1634 if(currentModule == "vslangproj90") 1635 replaceTokenSequence(tokens, "CsharpProjectConfigurationProperties3", "CSharpProjectConfigurationProperties3", true); 1636 1637 if(currentModule == "msdbg") 1638 replaceTokenSequence(tokens, "const DWORD S_UNKNOWN = 0x3;", "denum DWORD S_UNKNOWN = 0x3;", true); 1639 if(currentModule == "msdbg167") 1640 replaceTokenSequence(tokens, "__uuidof($data)", "$data.iid", true); 1641 if(currentModule == "activdbg") 1642 replaceTokenSequence(tokens, "const THREAD_STATE", "denum THREAD_STATE", true); 1643 1644 if(currentModule == "objidl") 1645 { 1646 replaceTokenSequence(tokens, "const OLECHAR *COLE_DEFAULT_PRINCIPAL", "denum const OLECHAR *COLE_DEFAULT_PRINCIPAL", true); 1647 replaceTokenSequence(tokens, "const void *COLE_DEFAULT_AUTHINFO", "denum const void *COLE_DEFAULT_AUTHINFO", true); 1648 } 1649 if(currentModule == "combaseapi") 1650 { 1651 replaceTokenSequence(tokens, "typedef enum CWMO_FLAGS", "typedef enum tagCWMO_FLAGS", true); 1652 } 1653 if(currentModule == "lmcons") 1654 { 1655 replaceTokenSequence(tokens, "alias NERR_BASE MIN_LANMAN_MESSAGE_ID;", "enum MIN_LANMAN_MESSAGE_ID = 2100;", true); // missing lmerr.h 1656 } 1657 if(currentModule == "winnt") 1658 { 1659 // Win SDK 8.1: remove translation to intrinsics 1660 replaceTokenSequence(tokens, "alias _InterlockedAnd InterlockedAnd;", "/+ $*", true); 1661 replaceTokenSequence(tokens, "InterlockedCompareExchange($args __in LONG ExChange, __in LONG Comperand);", "$* +/", true); 1662 replaceTokenSequence(tokens, "InterlockedOr(&Barrier, 0);", "InterlockedExchangeAdd(&Barrier, 0);", true); // InterlockedOr exist only as intrinsic 1663 } 1664 if(currentModule == "ocidl") 1665 { 1666 // move alias out of interface declaration, it causes circular definitions with dmd 2.065+ 1667 replaceTokenSequence(tokens, "interface IOleUndoManager : IUnknown { alias IID_IOleUndoManager SID_SOleUndoManager; $data }", 1668 "interface IOleUndoManager : IUnknown { $data }\n\nalias IID_IOleUndoManager SID_SOleUndoManager;", true); 1669 } 1670 1671 replaceTokenSequence(tokens, "extern const __declspec(selectany)", "dconst", true); 1672 replaceTokenSequence(tokens, "EXTERN_C $args;", "/+EXTERN_C $args;+/", true); 1673 replaceTokenSequence(tokens, "SAFEARRAY($args)", "SAFEARRAY/*($args)*/", true); 1674 1675 // remove forward declarations 1676 replaceTokenSequence(tokens, "enum $_ident;", "/+ enum $_ident; +/", true); 1677 replaceTokenSequence(tokens, "struct $_ident;", "/+ struct $_ident; +/", true); 1678 replaceTokenSequence(tokens, "struct __declspec($expr) $_ident;", "/+ struct __declspec($expr) $_ident; +/", true); 1679 replaceTokenSequence(tokens, "class $_ident;", "/+ class $_ident; +/", true); 1680 replaceTokenSequence(tokens, "interface $_ident;", "/+ interface $_ident; +/", true); 1681 replaceTokenSequence(tokens, "dispinterface $_ident;", "/+ dispinterface $_ident; +/", true); 1682 replaceTokenSequence(tokens, "coclass $_ident;", "/+ coclass $_ident; +/", true); 1683 replaceTokenSequence(tokens, "library $_ident {", "version(all)\n{ /+ library $_ident +/", true); 1684 replaceTokenSequence(tokens, "importlib($expr);", "/+importlib($expr);+/", true); 1685 1686 version(remove_pp) 1687 { 1688 string tsttxt = tokenListToString(tokens); 1689 1690 while(replaceTokenSequence(tokens, "$_note else version(all) { $if } else { $else }", "$_note $if", true) > 0 || 1691 replaceTokenSequence(tokens, "$_note else version(all) { $if } else version($ver) { $else_ver } else { $else }", "$_note $if", true) > 0 || 1692 replaceTokenSequence(tokens, "$_note else version(all) { $if } $_not else", "$_note $if\n$_not", true) > 0 || 1693 replaceTokenSequence(tokens, "$_note else version(none) { $if } else { $else }", "$_note $else", true) > 0 || 1694 replaceTokenSequence(tokens, "$_note else version(none) { $if } $_not else", "$_note $_not", true) > 0 || 1695 replaceTokenSequence(tokens, "version(pp_if) { $if } else { $else }", "$else", true) > 0 || 1696 replaceTokenSequence(tokens, "version(pp_if) { $if } $_not else", "$_not", true) > 0 || 1697 replaceTokenSequence(tokens, "version(pp_ifndef) { $if } else { $else }", "$if", true) > 0 || 1698 replaceTokenSequence(tokens, "version(pp_ifndef) { $if } $_not else", "$if\n$_not", true) > 0) 1699 { 1700 string rtsttxt = tokenListToString(tokens); 1701 } 1702 1703 string ntsttxt = tokenListToString(tokens); 1704 1705 } 1706 1707 while(replaceTokenSequence(tokens, "static if($expr) { } else { }", "", true) > 0 || 1708 replaceTokenSequence(tokens, "static if($expr) { } $_not else", "$_not", true) > 0 || 1709 replaceTokenSequence(tokens, "version($expr) { } else { }", "", true) > 0 || 1710 replaceTokenSequence(tokens, "version($expr) { } $_not else", "$_not", true) > 0) {} 1711 1712 // move declaration at the top of the interface below the interface while keeping the order 1713 replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data }", 1714 "interface $_ident1 : $_identbase { $data\n} __eo_interface", true); 1715 while(replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { typedef $args; $data } $tail __eo_interface", 1716 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ntypedef $args; __eo_interface", true) > 0 1717 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { denum $args; $data } $tail __eo_interface", 1718 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndenum $args; __eo_interface", true) > 0 1719 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { enum $args; $data } $tail __eo_interface", 1720 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nenum $args; __eo_interface", true) > 0 1721 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { dconst $_ident = $expr; $data } $tail __eo_interface", 1722 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndconst $_ident = $expr; __eo_interface", true) > 0 1723 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype $_ident = $expr; $data } $tail __eo_interface", 1724 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype $_ident = $expr; __eo_interface", true) > 0 1725 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype *$_ident = $expr; $data } $tail __eo_interface", 1726 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype *$_ident = $expr; __eo_interface", true) > 0 1727 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { struct $args; $data } $tail __eo_interface", 1728 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstruct $args; __eo_interface", true) > 0 1729 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { union $args; $data } $tail __eo_interface", 1730 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nunion $args; __eo_interface", true) > 0 1731 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { static if($expr) { $if } else { $else } $data } $tail __eo_interface", 1732 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstatic if($expr) {\n$if\n} else {\n$else\n} __eo_interface", true) > 0 1733 || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { version($expr) {/+ typedef $if } else { $else } $data } $tail __eo_interface", 1734 "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nversion($expr) {/+\ntypedef $if\n} else {\n$else\n} __eo_interface", true) > 0 1735 ) {} 1736 replaceTokenSequence(tokens, "__eo_interface", "", true); 1737 1738 replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data const DISPID $constids }", 1739 "interface $_ident1 : $_identbase { $data\n}\n\nconst DISPID $constids\n", true); 1740 version(none) 1741 { 1742 replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident2;", 1743 "enum $_ident2\n{\n$enums\n}", true); 1744 replaceTokenSequence(tokens, "typedef enum { $enums } $_ident2;", 1745 "enum $_ident2\n{\n$enums\n}", true); 1746 replaceTokenSequence(tokens, "typedef [$_ident3] enum $_ident1 { $enums } $_ident2;", 1747 "enum $_ident2\n{\n$enums\n}", true); 1748 replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", 1749 "enum $_ident2 : $_identbase\n{\n$enums\n}", true); 1750 } else { 1751 replaceTokenSequence(tokens, "typedef enum $_ident1 : uint { $enums } $_ident1;", 1752 "enum $_ident1 : uint\n{\n$enums\n}\n", true); 1753 1754 replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident1;", 1755 "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true); 1756 replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $ident2;", 1757 "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true); 1758 replaceTokenSequence(tokens, "typedef enum { $enums } $ident2;", 1759 "enum\n{\n$enums\n}\ntypedef int $ident2;", true); 1760 replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $_ident1;", 1761 "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true); 1762 replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $ident2;", 1763 "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true); 1764 replaceTokenSequence(tokens, "typedef [$info] enum { $enums } $ident2;", 1765 "enum [$info]\n{\n$enums\n}\ntypedef int $ident2;", true); 1766 replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", 1767 "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef $_identbase $_ident1;\ntypedef $_identbase $_ident2;", true); 1768 replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef [$info] $_identbase $_ident2;", 1769 "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef [$info] $_identbase $_ident2;", true); 1770 replaceTokenSequence(tokens, "enum $_ident1 { $enums };", 1771 "enum /+$_ident1+/ : int \n{\n$enums\n}\ntypedef int $_ident1;", true); 1772 replaceTokenSequence(tokens, "typedef enum $_ident1 $_ident1;", "/+ typedef enum $_ident1 $_ident1; +/", true); 1773 replaceTokenSequence(tokens, "enum $_ident1 $_ident2", "$_ident1 $_ident2", true); 1774 } 1775 replaceTokenSequence(tokens, "typedef _Struct_size_bytes_($args)", "typedef", true); 1776 1777 replaceTokenSequence(tokens, "__struct_bcount($args)", "[__struct_bcount($args)]", true); 1778 replaceTokenSequence(tokens, "struct $_ident : $_opt public $_ident2 {", "struct $_ident { $_ident2 base;", true); 1779 1780 replaceTokenSequence(tokens, "typedef struct { $data } $_ident2;", 1781 "struct $_ident2\n{\n$data\n}", true); 1782 replaceTokenSequence(tokens, "typedef struct { $data } $_ident2, $expr;", 1783 "struct $_ident2\n{\n$data\n}\ntypedef $_ident2 $expr;", true); 1784 replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $_ident2;", 1785 "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2;", true); 1786 replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $expr;", 1787 "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true); 1788 replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } $expr;", 1789 "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true); 1790 //replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } *$_ident2;", 1791 // "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true); 1792 //replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } *$_ident2;", 1793 // "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true); 1794 while(replaceTokenSequence(tokens, "struct { $data } $_ident2 $expr;", 1795 "struct _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true) > 0) {} 1796 1797 replaceTokenSequence(tokens, "[$_expr1 uuid($_identIID) $_expr2] interface $_identClass : $_identBase {", 1798 "dconst GUID IID_ __ $_identClass = $_identClass.iid;\n\n" ~ 1799 "interface $_identClass : $_identBase\n{\n static dconst GUID iid = $_identIID;\n\n", true); 1800 replaceTokenSequence(tokens, "[$_expr1 uuid($IID) $_expr2] interface $_identClass : $_identBase {", 1801 "dconst GUID IID_ __ $_identClass = $_identClass.iid;\n\n" ~ 1802 "interface $_identClass : $_identBase\n{\n static dconst GUID iid = { $IID };\n\n", true); 1803 1804 replaceTokenSequence(tokens, "[$_expr1 uuid($_identIID) $_expr2] coclass $_identClass {", 1805 "dconst GUID CLSID_ __ $_identClass = $_identClass.iid;\n\n" ~ 1806 "class $_identClass\n{\n static dconst GUID iid = $_identIID;\n\n", true); 1807 replaceTokenSequence(tokens, "[$_expr1 uuid($IID) $_expr2] coclass $_identClass {", 1808 "dconst GUID CLSID_ __ $_identClass = $_identClass.iid;\n\n" ~ 1809 "interface $_identClass\n{\n static dconst GUID iid = { $IID };\n\n", true); 1810 replaceTokenSequence(tokens, "coclass $_ident1 { $data }", "class $_ident1 { $data }", true); 1811 1812 // replaceTokenSequence(tokens, "assert $expr;", "assert($expr);", true); 1813 1814 replaceTokenSequence(tokens, "typedef union $_ident1 { $data } $_ident2 $expr;", 1815 "union $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2 $expr;", true); 1816 replaceTokenSequence(tokens, "typedef union $_ident1 switch($expr) $_ident2 { $data } $_ident3;", 1817 "union $_ident3 /+switch($expr) $_ident2 +/ { $data };", true); 1818 replaceTokenSequence(tokens, "typedef union switch($expr) { $data } $_ident3;", 1819 "union $_ident3 /+switch($expr) +/ { $data };", true); 1820 replaceTokenSequence(tokens, "union $_ident1 switch($expr) $_ident2 { $data };", 1821 "union $_ident1 /+switch($expr) $_ident2 +/ { $data };", true); 1822 replaceTokenSequence(tokens, "union $_ident1 switch($expr) $_ident2 { $data }", 1823 "union $_ident1 /+switch($expr) $_ident2 +/ { $data }", true); 1824 replaceTokenSequence(tokens, "case $_ident1:", "[case $_ident1:]", true); 1825 replaceTokenSequence(tokens, "default:", "[default:]", true); 1826 replaceTokenSequence(tokens, "union { $data } $_ident2 $expr;", 1827 "union _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true); 1828 1829 replaceTokenSequence(tokens, "typedef struct $_ident1 $expr;", "typedef $_ident1 $expr;", true); 1830 replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 $expr;", "typedef [$props] $_ident1 $expr;", true); 1831 1832 while (replaceTokenSequence(tokens, "typedef __nullterminated CONST $_identtype $_expr1, $args;", 1833 "typedef __nullterminated CONST $_identtype $_expr1; typedef __nullterminated CONST $_identtype $args;", true) > 0) {} 1834 while (replaceTokenSequence(tokens, "typedef CONST $_identtype $_expr1, $args;", 1835 "typedef CONST $_identtype $_expr1; typedef CONST $_identtype $args;", true) > 0) {} 1836 while (replaceTokenSequence(tokens, "typedef __nullterminated $_identtype $_expr1, $args;", 1837 "typedef __nullterminated $_identtype $_expr1; typedef __nullterminated $_identtype $args;", true) > 0) {} 1838 while (replaceTokenSequence(tokens, "typedef [$info] $_identtype $_expr1, $args;", 1839 "typedef [$info] $_identtype $_expr1; typedef [$info] $_identtype $args;", true) > 0) {} 1840 while (replaceTokenSequence(tokens, "typedef /+$info+/ $_identtype $_expr1, $args;", 1841 "typedef /+$info+/ $_identtype $_expr1; typedef /+$info+/ $_identtype $args;", true) > 0) {} 1842 1843 while (replaceTokenSequence(tokens, "typedef $_identtype $_expr1, $args;", 1844 "typedef $_identtype $_expr1; typedef $_identtype $args;", true) > 0) {} 1845 while (replaceTokenSequence(tokens, "typedef void $_expr1, $args;", 1846 "typedef void $_expr1; typedef void $args;", true) > 0) {} 1847 1848 replaceTokenSequence(tokens, "typedef $_ident1 $_ident1;", "", true); 1849 replaceTokenSequence(tokens, "typedef interface $_ident1 $_ident1;", "", true); 1850 1851 // Remote/Local version are made final to avoid placing them into the vtbl 1852 replaceTokenSequence(tokens, "[$pre call_as($arg) $post] $_not final", "[$pre call_as($arg) $post] final $_not", true); 1853 1854 // Some properties use the same name as the type of the return value 1855 replaceTokenSequence(tokens, "$_identFun([$data] $_identFun $arg)", "$_identFun([$data] .$_identFun $arg)", true); 1856 1857 // properties that have identically named getter and setter methods have reversed vtbl entries, 1858 // so we prepend put_,get_ or putref_ to the property 1859 if(startsWith(currentModule, "debugger80")) 1860 replaceTokenSequence(tokens, "HRESULT _stdcall", "HRESULT", true); // confusing following rules 1861 1862 replaceTokenSequence(tokens, "[$attr1 propput $attr2] HRESULT $_identFun", "[$attr1 propput $attr2]\n\tHRESULT put_ __ $_identFun", true); 1863 replaceTokenSequence(tokens, "[$attr1 propget $attr2] HRESULT $_identFun", "[$attr1 propget $attr2]\n\tHRESULT get_ __ $_identFun", true); 1864 replaceTokenSequence(tokens, "[$attr1 propputref $attr2] HRESULT $_identFun", "[$attr1 propputref $attr2]\n\tHRESULT putref_ __ $_identFun", true); 1865 1866 // VS2012 SDK 1867 if(currentModule == "webproperties") 1868 { 1869 replaceTokenSequence(tokens, "ClassFileItem([$data] ProjectItem $arg)", "ClassFileItem([$data] .ProjectItem $arg)", true); 1870 replaceTokenSequence(tokens, "Discomap([$data] ProjectItem $arg)", "Discomap([$data] .ProjectItem $arg)", true); 1871 } 1872 if(currentModule == "vsshell110") 1873 { 1874 // not inside #ifdef PROXYSTUB_BUILD 1875 replaceTokenSequence(tokens, "alias IID_SVsFileMergeService SID_SVsFileMergeService;", "// $*", true); 1876 1877 replaceTokenSequence(tokens, "__uuidof(SVsHierarchyManipulation)", "SVsHierarchyManipulation.iid", true); 1878 } 1879 if(currentModule == "vsshell166") 1880 { 1881 replaceTokenSequence(tokens, "__uuidof(IVsDebuggerLaunchAsync)", "IVsDebuggerLaunchAsync.iid", true); 1882 } 1883 if(currentModule == "vapiemp") 1884 { 1885 // CLSID_CVapiEMPDataSource undefined, create one 1886 replaceTokenSequence(tokens, "CVapiEMPDataSource.iid;", "uuid(\"{F1357394-9545-4cfd-AE2B-219C2A30C096}\");", true); 1887 } 1888 1889 // interface without base class is used as namespace 1890 replaceTokenSequence(tokens, "interface $_notIFace IUnknown { $_not static $data }", 1891 "/+interface $_notIFace {+/ $_not $data /+} interface $_notIFace+/", true); 1892 replaceTokenSequence(tokens, "dispinterface $_ident1 { $data }", "interface $_ident1 { $data }", true); 1893 replaceTokenSequence(tokens, "module $_ident1 { $data }", "/+module $_ident1 {+/ $data /+}+/", true); 1894 replaceTokenSequence(tokens, "properties:", "/+properties:+/", true); 1895 replaceTokenSequence(tokens, "methods:", "/+methods:+/", true); 1896 1897 replaceTokenSequence(tokens, "(void)", "()", true); 1898 replaceTokenSequence(tokens, "(VOID)", "()", true); 1899 replaceTokenSequence(tokens, "[in] ref $_ident", "in $_ident*", true); // in passes by value otherwise 1900 replaceTokenSequence(tokens, "[in,$data] ref $_ident", "[$data] in $_ident*", true); // in passes by value otherwise 1901 replaceTokenSequence(tokens, "[in]", "in", true); 1902 replaceTokenSequence(tokens, "[in,$_not out $data]", "[$_not $data] in", true); 1903 replaceTokenSequence(tokens, "[$args1]in[$args2]in", "[$args1][$args2]in", true); 1904 replaceTokenSequence(tokens, "in in", "in", true); 1905 replaceTokenSequence(tokens, "[*]", "[0]", true); 1906 replaceTokenSequence(tokens, "[default]", "/+[default]+/", true); 1907 1908 replaceExpressionTokens(tokens); 1909 1910 replaceTokenSequence(tokens, "__success($args)", "/+__success($args)+/", true); 1911 1912 version(all) { 1913 replaceTokenSequence(tokens, "typedef const", "typedef CONST", true); 1914 replaceTokenSequence(tokens, "extern \"C\"", "extern(C)", true); 1915 replaceTokenSequence(tokens, "extern \"C++\"", "extern(C++)", true); 1916 replaceTokenSequence(tokens, "__bcount($args)", "/+$*+/", true); 1917 replaceTokenSequence(tokens, "__bcount_opt($args)", "/+$*+/", true); 1918 replaceTokenSequence(tokens, "__in_bcount($args)", "/+$*+/", true); 1919 replaceTokenSequence(tokens, "__in_ecount($args)", "/+$*+/", true); 1920 replaceTokenSequence(tokens, "__in_xcount($args)", "/+$*+/", true); 1921 replaceTokenSequence(tokens, "__in_bcount_opt($args)", "/+$*+/", true); 1922 replaceTokenSequence(tokens, "__in_ecount_opt($args)", "/+$*+/", true); 1923 replaceTokenSequence(tokens, "__out_bcount($args)", "/+$*+/", true); 1924 replaceTokenSequence(tokens, "__out_xcount($args)", "/+$*+/", true); 1925 replaceTokenSequence(tokens, "__out_bcount_opt($args)", "/+$*+/", true); 1926 replaceTokenSequence(tokens, "__out_bcount_part($args)", "/+$*+/", true); 1927 replaceTokenSequence(tokens, "__out_bcount_part_opt($args)", "/+$*+/", true); 1928 replaceTokenSequence(tokens, "__out_bcount_full($args)", "/+$*+/", true); 1929 replaceTokenSequence(tokens, "__out_ecount($args)", "/+$*+/", true); 1930 replaceTokenSequence(tokens, "__out_ecount_opt($args)", "/+$*+/", true); 1931 replaceTokenSequence(tokens, "__out_ecount_part($args)", "/+$*+/", true); 1932 replaceTokenSequence(tokens, "__out_ecount_part_opt($args)", "/+$*+/", true); 1933 replaceTokenSequence(tokens, "__out_ecount_full($args)", "/+$*+/", true); 1934 replaceTokenSequence(tokens, "__out_data_source($args)", "/+$*+/", true); 1935 replaceTokenSequence(tokens, "__out_xcount_opt($args)", "/+$*+/", true); 1936 replaceTokenSequence(tokens, "__out_has_type_adt_props($args)", "/+$*+/", true); 1937 1938 replaceTokenSequence(tokens, "__inout_bcount($args)", "/+$*+/", true); 1939 replaceTokenSequence(tokens, "__inout_ecount($args)", "/+$*+/", true); 1940 replaceTokenSequence(tokens, "__inout_xcount($args)", "/+$*+/", true); 1941 replaceTokenSequence(tokens, "__inout_bcount_opt($args)", "/+$*+/", true); 1942 replaceTokenSequence(tokens, "__inout_ecount_opt($args)", "/+$*+/", true); 1943 replaceTokenSequence(tokens, "__inout_bcount_part($args)", "/+$*+/", true); 1944 replaceTokenSequence(tokens, "__inout_ecount_part($args)", "/+$*+/", true); 1945 replaceTokenSequence(tokens, "__inout_bcount_part_opt($args)", "/+$*+/", true); 1946 replaceTokenSequence(tokens, "__inout_ecount_part_opt($args)", "/+$*+/", true); 1947 replaceTokenSequence(tokens, "__deref_out_ecount($args)", "/+$*+/", true); 1948 replaceTokenSequence(tokens, "__deref_out_bcount($args)", "/+$*+/", true); 1949 replaceTokenSequence(tokens, "__deref_out_xcount($args)", "/+$*+/", true); 1950 replaceTokenSequence(tokens, "__deref_out_ecount_opt($args)", "/+$*+/", true); 1951 replaceTokenSequence(tokens, "__deref_out_bcount_opt($args)", "/+$*+/", true); 1952 replaceTokenSequence(tokens, "__deref_out_xcount_opt($args)", "/+$*+/", true); 1953 replaceTokenSequence(tokens, "__deref_opt_out_bcount_full($args)", "/+$*+/", true); 1954 replaceTokenSequence(tokens, "__deref_inout_ecount_z($args)", "/+$*+/", true); 1955 replaceTokenSequence(tokens, "__field_bcount($args)", "/+$*+/", true); 1956 replaceTokenSequence(tokens, "__field_bcount_opt($args)", "/+$*+/", true); 1957 replaceTokenSequence(tokens, "__field_ecount($args)", "/+$*+/", true); 1958 replaceTokenSequence(tokens, "__field_ecount_opt($args)", "/+$*+/", true); 1959 replaceTokenSequence(tokens, "__in_range($args)", "/+$*+/", true); 1960 replaceTokenSequence(tokens, "__range($args)", "/+$*+/", true); 1961 replaceTokenSequence(tokens, "__declspec($args)", "/+$*+/", true); 1962 replaceTokenSequence(tokens, "__in_range($args)", "/+$*+/", true); 1963 replaceTokenSequence(tokens, "__transfer($args)", "/+$*+/", true); 1964 1965 replaceTokenSequence(tokens, "__drv_functionClass($args)", "/+$*+/", true); 1966 replaceTokenSequence(tokens, "__drv_maxIRQL($args)", "/+$*+/", true); 1967 replaceTokenSequence(tokens, "__drv_when($args)", "/+$*+/", true); 1968 replaceTokenSequence(tokens, "__drv_freesMem($args)", "/+$*+/", true); 1969 replaceTokenSequence(tokens, "__drv_preferredFunction($args)", "/+$*+/", true); 1970 replaceTokenSequence(tokens, "__drv_allocatesMem($args)", "/+$*+/", true); 1971 1972 // Win SDK 8.0 1973 replaceTokenSequence(tokens, "_IRQL_requires_same_", "/+$*+/", true); 1974 replaceTokenSequence(tokens, "_Function_class_($args)", "/+$*+/", true); 1975 replaceTokenSequence(tokens, "_Inout_cap_($args)", "/+$*+/", true); 1976 replaceTokenSequence(tokens, "_Inout_count_($args)", "/+$*+/", true); 1977 replaceTokenSequence(tokens, "_Inout_updates_($args)", "/+$*+/", true); 1978 replaceTokenSequence(tokens, "_Inout_updates_z_($args)", "/+$*+/", true); 1979 replaceTokenSequence(tokens, "_Inout_updates_opt_($args)", "/+$*+/", true); 1980 replaceTokenSequence(tokens, "_Inout_updates_bytes_($args)", "/+$*+/", true); 1981 replaceTokenSequence(tokens, "_Inout_updates_bytes_opt_($args)", "/+$*+/", true); 1982 replaceTokenSequence(tokens, "_Inout_updates_bytes_to_opt_($args)", "/+$*+/", true); 1983 replaceTokenSequence(tokens, "_Interlocked_operand_", "/+$*+/", true); 1984 replaceTokenSequence(tokens, "_Struct_size_bytes_($args)", "/+$*+/", true); 1985 replaceTokenSequence(tokens, "_Out_writes_($args)", "/+$*+/", true); 1986 replaceTokenSequence(tokens, "_Out_writes_opt_($args)", "/+$*+/", true); 1987 replaceTokenSequence(tokens, "_Out_writes_to_($args)", "/+$*+/", true); 1988 replaceTokenSequence(tokens, "_Out_writes_to_opt_($args)", "/+$*+/", true); 1989 replaceTokenSequence(tokens, "_Out_writes_bytes_($args)", "/+$*+/", true); 1990 replaceTokenSequence(tokens, "_Out_writes_bytes_opt_($args)", "/+$*+/", true); 1991 replaceTokenSequence(tokens, "_Out_writes_bytes_to_($args)", "/+$*+/", true); 1992 replaceTokenSequence(tokens, "_Out_writes_bytes_to_opt_($args)", "/+$*+/", true); 1993 replaceTokenSequence(tokens, "_Out_writes_bytes_all_($args)", "/+$*+/", true); 1994 replaceTokenSequence(tokens, "_Out_cap_($args)", "/+$*+/", true); 1995 replaceTokenSequence(tokens, "_Out_z_cap_($args)", "/+$*+/", true); 1996 replaceTokenSequence(tokens, "_In_reads_($args)", "/+$*+/", true); 1997 replaceTokenSequence(tokens, "_In_count_($args)", "/+$*+/", true); 1998 replaceTokenSequence(tokens, "_In_reads_opt_($args)", "/+$*+/", true); 1999 replaceTokenSequence(tokens, "_In_reads_bytes_($args)", "/+$*+/", true); 2000 replaceTokenSequence(tokens, "_In_reads_bytes_opt_($args)", "/+$*+/", true); 2001 replaceTokenSequence(tokens, "_In_NLS_string_($args)", "/+$*+/", true); 2002 replaceTokenSequence(tokens, "_When_($args)", "/+$*+/", true); 2003 replaceTokenSequence(tokens, "_At_($args)", "/+$*+/", true); 2004 replaceTokenSequence(tokens, "_Post_readable_size_($args)", "/+$*+/", true); 2005 replaceTokenSequence(tokens, "_Post_writable_byte_size_($args)", "/+$*+/", true); 2006 replaceTokenSequence(tokens, "_Post_equal_to_($args)", "/+$*+/", true); 2007 replaceTokenSequence(tokens, "_Ret_writes_maybenull_z_($args)", "/+$*+/", true); 2008 replaceTokenSequence(tokens, "_Ret_writes_($args)", "/+$*+/", true); 2009 replaceTokenSequence(tokens, "_Ret_range_($args)", "/+$*+/", true); 2010 replaceTokenSequence(tokens, "_Return_type_success_($args)", "/+$*+/", true); 2011 replaceTokenSequence(tokens, "_Outptr_result_buffer_($args)", "/+$*+/", true); 2012 replaceTokenSequence(tokens, "_Outptr_result_bytebuffer_($args)", "/+$*+/", true); 2013 replaceTokenSequence(tokens, "_Outptr_result_buffer_maybenull_($args)", "/+$*+/", true); 2014 replaceTokenSequence(tokens, "_Outptr_opt_result_bytebuffer_all_($args)", "/+$*+/", true); 2015 replaceTokenSequence(tokens, "_Outptr_opt_result_buffer_($args)", "/+$*+/", true); 2016 replaceTokenSequence(tokens, "_Releases_exclusive_lock_($args)", "/+$*+/", true); 2017 replaceTokenSequence(tokens, "_Releases_shared_lock_($args)", "/+$*+/", true); 2018 replaceTokenSequence(tokens, "_Acquires_exclusive_lock_($args)", "/+$*+/", true); 2019 replaceTokenSequence(tokens, "_Acquires_shared_lock_($args)", "/+$*+/", true); 2020 2021 // Win SDK 8.1 2022 replaceTokenSequence(tokens, "_Post_satisfies_($args)", "/+$*+/", true); 2023 replaceTokenSequence(tokens, "_Post_readable_byte_size_($args)", "/+$*+/", true); 2024 replaceTokenSequence(tokens, "_Ret_reallocated_bytes_($args)", "/+$*+/", true); 2025 2026 // Win SDK 10.0 2027 replaceTokenSequence(tokens, "_Translates_Win32_to_HRESULT_($args)", "/+$*+/", true); 2028 replaceTokenSequence(tokens, "_Always_($args)", "/+$*+/", true); 2029 replaceTokenSequence(tokens, "__control_entrypoint($args)", "/+$*+/", true); 2030 2031 replaceTokenSequence(tokens, "__assume_bound($args);", "/+$*+/", true); 2032 replaceTokenSequence(tokens, "__asm{$args}$_opt;", "assert(false, \"asm not translated\"); asm{naked; nop; /+$args+/}", true); 2033 replaceTokenSequence(tokens, "__asm $_not{$stmt}", "assert(false, \"asm not translated\"); asm{naked; nop; /+$_not $stmt+/} }", true); 2034 replaceTokenSequence(tokens, "sizeof($_ident)", "$_ident.sizeof", true); 2035 replaceTokenSequence(tokens, "sizeof($args)", "($args).sizeof", true); 2036 2037 // Win SDK 10.0,17136,0 2038 replaceTokenSequence(tokens, "_Out_writes_z_($args)", "/+$*+/", true); 2039 replaceTokenSequence(tokens, "_IRQL_requires_max_($args)", "/+$*+/", true); 2040 2041 // bitfields: 2042 replaceTokenSequence(tokens, "$_identtype $_identname : $_num;", "__bf $_identtype, __quote $_identname __quote, $_num __eobf", true); 2043 replaceTokenSequence(tokens, "$_identtype $_identname : $_ident;", "__bf $_identtype, __quote $_identname __quote, $_ident __eobf", true); 2044 replaceTokenSequence(tokens, "$_identtype $_identname : $_num - $_identconst;", "__bf $_identtype, __quote $_identname __quote, $_num - $_identconst __eobf", true); 2045 replaceTokenSequence(tokens, "$_identtype : $_num;", "__bf $_identtype, __quote __quote, $_num __eobf", true); 2046 replaceTokenSequence(tokens, "__eobf __bf", ",\n\t", true); 2047 replaceTokenSequence(tokens, "__bf", "mixin(bitfields!(", true); 2048 replaceTokenSequence(tokens, "__eobf", "));", true); 2049 2050 // remove version between identifiers, must be declaration 2051 while(replaceTokenSequence(tokens, "$_ident1 version(all) { $if } else { $else } $_ident2", "$_ident1 $if $_ident2", true) > 0 2052 || replaceTokenSequence(tokens, "$_ident1 version(all) { $if } $_ident2", "$_ident1 $if $_ident2", true) > 0 2053 || replaceTokenSequence(tokens, "$_ident1 version(none) { $if } else { $else } $_ident2", "$_ident1 $else $_ident2", true) > 0 2054 || replaceTokenSequence(tokens, "$_ident1 version(none) { $if } $_ident2", "$_ident1 $_ident2", true) > 0) {} 2055 2056 // __stdcall 2057 version(none) 2058 { 2059 replaceTokenSequence(tokens, "$_identtype NTAPI", "extern(Windows) $_identtype", true); 2060 replaceTokenSequence(tokens, "$_identtype (NTAPI", "extern(Windows) $_identtype (", true); 2061 replaceTokenSequence(tokens, "$_identtype WINAPI", "extern(Windows) $_identtype", true); 2062 replaceTokenSequence(tokens, "$_identtype (WINAPI", "extern(Windows) $_identtype (", true); 2063 replaceTokenSequence(tokens, "$_identtype (/+$_ident+/ WINAPI", "extern(Windows) $_identtype (", true); 2064 replaceTokenSequence(tokens, "$_identtype APIENTRY", "extern(Windows) $_identtype", true); 2065 replaceTokenSequence(tokens, "$_identtype (APIENTRY", "extern(Windows) $_identtype (", true); 2066 replaceTokenSequence(tokens, "$_identtype (CALLBACK", "extern(Windows) $_identtype (", true); 2067 } else { 2068 replaceTokenSequence(tokens, "NTAPI", "extern(Windows)", true); 2069 replaceTokenSequence(tokens, "WINAPI", "extern(Windows)", true); 2070 replaceTokenSequence(tokens, "APIENTRY", "extern(Windows)", true); 2071 replaceTokenSequence(tokens, "CALLBACK", "extern(Windows)", true); 2072 } 2073 2074 replaceTokenSequence(tokens, "$_identtype extern(Windows)", "extern(Windows) $_identtype", true); 2075 replaceTokenSequence(tokens, "$_identtype* extern(Windows)", "extern(Windows) $_identtype*", true); 2076 replaceTokenSequence(tokens, "$_identtype (extern(Windows)", "extern(Windows) $_identtype (", true); 2077 replaceTokenSequence(tokens, "$_identtype* (extern(Windows)", "extern(Windows) $_identtype* (", true); 2078 replaceTokenSequence(tokens, "$_identtype (/+$_ident+/ extern(Windows)", "extern(Windows) $_identtype (", true); 2079 2080 replaceTokenSequence(tokens, "DECLARE_HANDLE($_ident);", "typedef HANDLE $_ident;", true); 2081 replaceTokenSequence(tokens, "__inline $_identFun(", "inline int $_identFun(", true); 2082 2083 replaceTokenSequence(tokens, "HRESULT($_ident)($_args);", "HRESULT $_ident($_args);", true); 2084 replaceTokenSequence(tokens, "$_identType (*$_identFunc)($_args)", "$_identType function($_args) $_identFunc", true); 2085 replaceTokenSequence(tokens, "void* (*$_identFunc)($_args)", "void* function($_args) $_identFunc", true); 2086 replaceTokenSequence(tokens, "$_identType (__stdcall *$_identFunc)($_args)", "$_identType __stdcall function($_args) $_identFunc", true); 2087 replaceTokenSequence(tokens, "$_identType (__cdecl *$_identFunc)($_args)", "$_identType __cdecl function($_args) $_identFunc", true); 2088 replaceTokenSequence(tokens, "$_identType (/+__cdecl+/ *$_identFunc)($_args)", "$_identType __cdecl function($_args) $_identFunc", true); 2089 } 2090 version(targetD2) 2091 { 2092 replaceTokenSequence(tokens, "$_ident const volatile*", "volatile dconst($_ident)*", true); 2093 replaceTokenSequence(tokens, "CONST FAR*", "CONST*", true); 2094 replaceTokenSequence(tokens, "$_ident const*", "dconst($_ident)*", true); 2095 replaceTokenSequence(tokens, "const $_ident*", "dconst($_ident)*", true); 2096 replaceTokenSequence(tokens, "CONST $_ident*", "dconst($_ident)*", true); 2097 } 2098 else 2099 { 2100 replaceTokenSequence(tokens, "const $_ident*", "/+const+/ $_ident*", true); 2101 } 2102 replaceTokenSequence(tokens, "in const $_not(", "in $_not", false); 2103 2104 2105 if(currentModule == "vsshelluuids") 2106 { 2107 replaceTokenSequence(tokens, "denum GUID uuid_IVsDebugger3 = uuid($uid);$data denum GUID uuid_IVsDebugger3", 2108 "$data\ndenum GUID uuid_IVsDebugger3",true); 2109 replaceTokenSequence(tokens, "denum GUID uuid_IVsDebugLaunchHook = uuid($uid);$data denum GUID uuid_IVsDebugLaunchHook", 2110 "$data\ndenum GUID uuid_IVsDebugLaunchHook",true); 2111 } 2112 if(currentModule == "mnuhelpids") 2113 { 2114 replaceTokenSequence(tokens, "denum icmdHelpManager = $data; denum icmdHelpManager", "denum icmdHelpManager", true); 2115 } 2116 2117 if(currentModule == "prsht") 2118 { 2119 replaceTokenSequence(tokens, "alias _PROPSHEETPAGEA $_ident;", "alias $_ident _PROPSHEETPAGEA;", true); 2120 replaceTokenSequence(tokens, "alias _PROPSHEETPAGEW $_ident;", "alias $_ident _PROPSHEETPAGEW;", true); 2121 } 2122 if(currentModule == "vsscceng") 2123 { 2124 replaceTokenSequence(tokens, "extern(C++) { $data }", "/+ $* +/", true); 2125 } 2126 if(currentModule == "winnls") 2127 { 2128 replaceTokenSequence(tokens, "alias MUI_CALLBACK_FLAG_UPGRADED_INSTALLATION $_ident;", "// $*", true); 2129 } 2130 if(currentModule == "basetsd") 2131 { 2132 // Deprecation: integral promotion not done for `~cast(ubyte)...` 2133 replaceTokenSequence(tokens, "~MAXHALF_PTR", "~cast(int)MAXHALF_PTR", true); 2134 replaceTokenSequence(tokens, "~(cast(UINT8)0)", "~0", true); 2135 replaceTokenSequence(tokens, "~(cast(UINT16)0)", "~0", true); 2136 replaceTokenSequence(tokens, "~MAXINT8", "~cast(int)MAXINT8", true); 2137 replaceTokenSequence(tokens, "~MAXINT16", "~cast(int)MAXINT16", true); 2138 2139 } 2140 //replaceTokenSequence(tokens, "[$args]", "\n\t\t/+[$args]+/", true); 2141 2142 TokenIterator inAlias = tokens.end(); 2143 for(TokenIterator tokIt = tokens.begin(); !tokIt.atEnd(); ++tokIt) 2144 { 2145 Token tok = *tokIt; 2146 //tok.pretext = tok.pretext.replace("//D", ""); 2147 tok.text = translateToken(tok.text); 2148 if(tok.text == "[" && tokIt[1].text == "]") 2149 { 2150 if(tokIt[2].text == ";") 2151 tokIt[1].pretext ~= "0"; // in struct 2152 else if(tokIt[2].text == "," || tokIt[2].text == ")" && tokIt[-1].type == Token.Identifier) 2153 { 2154 tok.text = ""; 2155 tokIt[1].text = ""; 2156 tokIt[-1].pretext ~= "*"; // in function argument 2157 } 2158 } 2159 else if(tok.text == "[" && tokIt[1].text != "]") 2160 { 2161 if((tokIt.atBegin() || tokIt[-1].text != "{" || tokIt[-2].text != "=") && 2162 (tokIt[1].type != Token.Number || tokIt[2].text != "]") && 2163 (tokIt[2].text != "]" || tokIt[3].text != ";")) 2164 { 2165 TokenIterator bit = tokIt; 2166 //if(advanceToClosingBracket(bit) && bit.text != ";") 2167 { 2168 if(tokIt.atBegin || (tokIt[-1].text != "(" && tokIt[-1].text != "alias")) 2169 if (tok.pretext.indexOf('\n') < 0) 2170 tok.pretext ~= "\n\t\t"; 2171 tok.text = "/+["; 2172 } 2173 } 2174 } 2175 else if(tok.text == "]" && tokIt[-1].text != "[") 2176 { 2177 TokenIterator openit = tokIt; 2178 if(retreatToOpeningBracket(openit) && 2179 (openit.atBegin || (openit-1).atBegin || openit[-1].text != "{" || openit[-2].text != "=")) 2180 if((tokIt[-1].type != Token.Number || tokIt[-2].text != "[") && 2181 (tokIt[-2].text != "[" || tokIt[1].text != ";")) 2182 tok.text = "]+/"; 2183 } 2184 else if(tok.text == "struct" && tokIt[1].type == Token.Identifier && tokIt[2].text != "{") 2185 { 2186 if(tokIt[1].text != "__" && tokIt[1].text != "_") 2187 { 2188 // forward reference to struct type 2189 tok.text = ""; 2190 if(tokIt[1].text.startsWith("tag")) 2191 tokIt[1].text = tokIt[1].text[3..$]; 2192 } 2193 } 2194 else if((tok.text == "GUID" || tok.text == "IID" || tok.text == "CLSID") && 2195 tokIt[1].type == Token.Identifier && tokIt[2].text == "=" && tokIt[3].text == "{") 2196 { 2197 convertGUID(tokIt + 4); 2198 } 2199 else if(tok.text == "__quote") 2200 { 2201 tok.pretext = ""; 2202 tok.text = "\""; 2203 tokIt[1].pretext = ""; 2204 } 2205 else if(tok.text == "*" && !tokIt.atBegin() && isClassIdentifier(tokIt[-1].text)) 2206 { 2207 tok.text = ""; 2208 if(tok.pretext.empty && tokIt[1].pretext.empty) 2209 tok.pretext = " "; 2210 } 2211 else if(tok.type == Token.String && tok.text.length > 4 && tok.text[0] == '\'') 2212 tok.text = "\"" ~ tok.text[1 .. $-1] ~ "\""; 2213 2214 else if(tok.text == "in" && (tokIt[1].text in classes)) 2215 tok.text = "/+[in]+/"; 2216 2217 else if(tok.text == "alias") 2218 inAlias = tokIt; 2219 else if(tok.text == ";" && !inAlias.atEnd()) 2220 { 2221 if(tokIt[-1].type == Token.Identifier) 2222 { 2223 if (string* s = tokIt[-1].text in aliases) 2224 { 2225 if(*s != currentFullModule) 2226 { 2227 inAlias.pretext ~= "/+"; 2228 tok.text ~= "+/"; 2229 if(!currentImports.contains(*s)) 2230 addedImports.addunique(*s); 2231 } 2232 } 2233 else 2234 aliases[tokIt[-1].text] = currentFullModule; 2235 } 2236 inAlias = tokens.end(); 2237 } 2238 } 2239 2240 // vsshell.idl: 2241 replaceTokenSequence(tokens, "DEFINE_GUID($_ident,$_num1,$_num2,$_num3,$_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB)", 2242 "const GUID $_ident = { $_num1,$_num2,$_num3, [ $_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB ] }", true); 2243 replaceTokenSequence(tokens, "EXTERN_GUID($_ident,$_num1,$_num2,$_num3,$_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB)", 2244 "const GUID $_ident = { $_num1,$_num2,$_num3, [ $_num4,$_num5,$_num6,$_num7,$_num8,$_num9,$_numA,$_numB ] }", true); 2245 2246 // VS 16.6: untranslatable C++ 2247 replaceTokenSequence(tokens, "idl_bool IsLegacyVTIntPtrVARIANT $code GetVSCOOKIEVariantValHelper($args) { $code2 }", 2248 "", false); 2249 2250 // combaseapi.h: 2251 replaceTokenSequence(tokens, "alias int $_ident = $_num;", "enum int $_ident = $_num;", true); 2252 2253 // C style array declarations to S style 2254 replaceTokenSequence(tokens, "$_identtype $_identvar[$dim]", "$_identtype[$dim] $_identvar", true); 2255 replaceTokenSequence(tokens, "$_identtype[$dim1] $_identvar[$dim2]", "$_identtype[$dim1][$dim2] $_identvar", true); 2256 // handle some pointer array explicitely to avoid ambiguities with expressions 2257 replaceTokenSequence(tokens, "void* $_identvar[$dim]", "void*[$dim] $_identvar", true); 2258 replaceTokenSequence(tokens, "ubyte* $_identvar[$dim]", "ubyte*[$dim] $_identvar", true); 2259 replaceTokenSequence(tokens, "ushort* $_identvar[$dim]", "ushort*[$dim] $_identvar", true); 2260 replaceTokenSequence(tokens, "UUID* $_identvar[$dim]", "UUID*[$dim] $_identvar", true); 2261 replaceTokenSequence(tokens, "RPC_IF_ID* $_identvar[$dim]", "RPC_IF_ID*[$dim] $_identvar", true); 2262 2263 string txt = tokenListToString(tokens, true); 2264 return txt; 2265 } 2266 2267 string translateToken(string text) 2268 { 2269 switch(text) 2270 { 2271 case "denum": return "enum"; 2272 case "dconst": return "const"; 2273 2274 case "_stdcall": return "/*_stdcall*/"; 2275 case "_fastcall": return "/*_fastcall*/"; 2276 case "__stdcall": return "/*__stdcall*/"; 2277 case "__cdecl": return "/*__cdecl*/"; 2278 case "__gdi_entry": return "/*__gdi_entry*/"; 2279 2280 //case "const": return "/*const*/"; 2281 case "inline": return "/*inline*/"; 2282 case "__int64": return "long"; 2283 case "__int32": return "int"; 2284 case "__int3264": return "int"; 2285 case "long": return "int"; 2286 case "typedef": return "alias"; 2287 case "bool": return "idl_bool"; 2288 case "GUID_NULL": return "const_GUID_NULL"; 2289 case "NULL": return "null"; 2290 case "scope": return "idl_scope"; 2291 2292 // winbase annotations 2293 case "__in": 2294 case "__in_opt": 2295 case "__in_z_opt": 2296 case "__in_bound": 2297 2298 case "__allocator": 2299 case "__out": 2300 case "__out_opt": 2301 case "__out_z": 2302 case "__inout": 2303 case "__inout_z": 2304 case "__deref": 2305 case "__deref_inout_opt": 2306 case "__deref_out_opt": 2307 case "__deref_inout": 2308 case "__inout_opt": 2309 case "__deref_out": 2310 case "__deref_opt_out": 2311 case "__deref_opt_out_opt": 2312 case "__deref_opt_inout_opt": 2313 2314 case "__callback": 2315 case "__format_string": 2316 case "__reserved": 2317 case "__notnull": 2318 case "__nullterminated": 2319 case "__nullnullterminated": 2320 case "__possibly_notnullterminated": 2321 2322 case "__drv_interlocked": 2323 case "__drv_sameIRQL": 2324 case "__drv_inTry": 2325 case "__drv_aliasesMem": 2326 2327 case "__post": 2328 case "__notvalid": 2329 case "__analysis_noreturn": 2330 2331 // Windows SDK 8.0 2332 case "_Outptr_": 2333 case "_Outptr_opt_": 2334 case "_COM_Outptr_": 2335 case "_In_z_": 2336 case "_In_opt_z_": 2337 case "_Pre_": 2338 case "_Pre_valid_": 2339 case "_Pre_z_": 2340 case "_Pre_opt_valid_": 2341 case "_Pre_maybenull_": 2342 case "_Post_valid_": 2343 case "_Post_invalid_": 2344 case "_Post_": 2345 case "_Post_z_": 2346 case "_Deref_opt_out_opt_": 2347 case "_Post_equals_last_error_": 2348 case "_Outptr_opt_result_maybenull_": 2349 case "_Check_return_": 2350 case "_Must_inspect_result_": 2351 case "_Frees_ptr_opt_": 2352 case "_Reserved_": 2353 case "_Ret_maybenull_": 2354 case "_Ret_opt_": 2355 case "_Printf_format_string_": 2356 2357 // Windows SDK 8.1 2358 case "_Field_z_": 2359 case "_Pre_notnull_": 2360 case "_Frees_ptr_": 2361 2362 // Windows SDK 10.0 2363 case "NOT_BUILD_WINDOWS_DEPRECATE": 2364 case "DECLSPEC_ALLOCATOR": 2365 2366 // Windows SDK 10.0.14393.0 2367 case "_Outptr_result_z_": 2368 2369 // Windows SDK 10.0.15063.0 2370 case "_Post_ptr_invalid_": 2371 2372 // VS14 SDK comment after #endif 2373 case "PROXYSTUB_BUILD": 2374 return "/*" ~ text ~ "*/"; 2375 2376 case "__checkReturn": return "/*__checkReturn*/"; 2377 case "volatile": return "/*volatile*/"; 2378 case "__inline": return "/*__inline*/"; 2379 case "__forceinline": return "/*__forceinline*/"; 2380 case "IN": return "/*IN*/"; 2381 case "OUT": return "/*OUT*/"; 2382 case "NEAR": return "/*NEAR*/"; 2383 case "FAR": return "/*FAR*/"; 2384 case "HUGEP": return "/*HUGEP*/"; 2385 case "OPTIONAL": return "/*OPTIONAL*/"; 2386 case "DECLSPEC_NORETURN": return "/*DECLSPEC_NORETURN*/"; 2387 case "CONST": return "/*CONST*/"; 2388 case "VOID": return "void"; 2389 case "wchar_t": return "wchar"; 2390 case "->": return "."; 2391 2392 // vslangproj.d 2393 case "prjBuildActionCustom": return "prjBuildActionEmbeddedResource"; 2394 2395 // wingdi.d: wrong octal number in SDK v6.0A 2396 case "02500": return "2500"; 2397 2398 default: 2399 if(string* ps = text in tokImports) 2400 text = *ps ~ "." ~ text; 2401 break; 2402 } 2403 return text; 2404 } 2405 2406 void addSource(string file) 2407 { 2408 string base = baseName(file); 2409 if(excludefiles.contains(base)) 2410 return; 2411 2412 if(!srcfiles.contains(file)) 2413 srcfiles ~= file; 2414 } 2415 2416 void addSourceByPattern(string file) 2417 { 2418 SpanMode mode = SpanMode.shallow; 2419 if (file[0] == '+') 2420 { 2421 mode = SpanMode.depth; 2422 file = file[1..$]; 2423 } 2424 string path = dirName(file); 2425 string pattern = baseName(file); 2426 foreach (string name; dirEntries(path, mode)) 2427 if (globMatch(baseName(name), pattern)) 2428 { 2429 addSource(name); 2430 if (pattern[0] != '*') 2431 break; // don't add optional files twice 2432 } 2433 } 2434 2435 void addSources(string file) 2436 { 2437 if (indexOf(file, '*') >= 0 || indexOf(file, '?') >= 0) 2438 addSourceByPattern("+" ~ file); 2439 else 2440 { 2441 if(!exists(file)) 2442 file = dirName(file) ~ "\\shared\\" ~ baseName(file); 2443 if(!exists(file)) 2444 file = replace(file, "\\shared\\", "\\um\\"); 2445 addSource(file); 2446 } 2447 } 2448 2449 string fileToModule(string file) 2450 { 2451 auto len = file.startsWith(win_d_path) ? win_d_path.length : vsi_d_path.length; 2452 2453 file = file[len .. $]; 2454 if (_endsWith(file,".d")) 2455 file = file[0 .. $-2]; 2456 file = replace(file, "/", "."); 2457 file = replace(file, "\\", "."); 2458 return file; 2459 } 2460 2461 string makehdr(string file, string d_file) 2462 { 2463 string pkg = d_file.startsWith(win_d_path) ? packageWin : packageVSI; 2464 string name = fileToModule(d_file); 2465 string hdr; 2466 hdr ~= "// File generated by idl2d from\n"; 2467 hdr ~= "// " ~ file ~ "\n"; 2468 hdr ~= "module " ~ pkg ~ name ~ ";\n\n"; 2469 //hdr ~= "import std.c.windows.windows;\n"; 2470 //hdr ~= "import std.c.windows.com;\n"; 2471 //hdr ~= "import idl.pp_util;\n"; 2472 if(pkg == packageVSI) 2473 hdr ~= "import " ~ packageNF ~ "vsi;\n"; 2474 else 2475 hdr ~= "import " ~ packageNF ~ "base;\n"; 2476 hdr ~= "\n"; 2477 2478 foreach(imp; addedImports) 2479 hdr ~= "import " ~ imp ~ ";\n"; 2480 2481 if(currentModule == "vsshell") 2482 hdr ~= "import " ~ packageWin ~ "commctrl;\n"; 2483 if(currentModule == "vsshlids") 2484 hdr ~= "import " ~ packageVSI ~ "oleipc;\n"; 2485 else if(currentModule == "debugger80") 2486 hdr ~= "import " ~ packageWin ~ "oaidl;\n" 2487 ~ "import " ~ packageVSI ~ "dte80a;\n"; 2488 else if(currentModule == "xmldomdid") 2489 hdr ~= "import " ~ packageWin ~ "idispids;\n"; 2490 else if(currentModule == "xmldso") 2491 hdr ~= "import " ~ packageWin ~ "xmldom;\n"; 2492 else if(currentModule == "commctrl") 2493 hdr ~= "import " ~ packageWin ~ "objidl;\n"; 2494 else if(currentModule == "shellapi") 2495 hdr ~= "import " ~ packageWin ~ "iphlpapi;\n"; 2496 else if(currentModule == "ifmib") 2497 hdr ~= "import " ~ packageWin ~ "iprtrmib;\n"; 2498 else if(currentModule == "ipmib") 2499 hdr ~= "import " ~ packageWin ~ "iprtrmib;\n"; 2500 else if(currentModule == "tcpmib") 2501 hdr ~= "import " ~ packageWin ~ "iprtrmib;\n"; 2502 else if(currentModule == "udpmib") 2503 hdr ~= "import " ~ packageWin ~ "iprtrmib;\n"; 2504 else if(currentModule == "vssolutn") 2505 hdr ~= "import " ~ packageWin ~ "winnls;\n"; 2506 else if(currentModule == "dpa_dsa") 2507 hdr ~= "import " ~ packageWin ~ "objidlbase;\n"; 2508 2509 hdr ~= "\n"; 2510 2511 version(static_if_to_version) 2512 { 2513 version(remove_pp) {} else 2514 hdr ~= "version = pp_ifndef;\n\n"; 2515 } 2516 2517 return hdr; 2518 } 2519 2520 void rewrite_vsiproject(string sources) 2521 { 2522 string projfile = sdk_d_path ~ "vsi.visualdproj"; 2523 if(!exists(projfile)) 2524 return; 2525 string txt = cast(string)(std.file.read(projfile)); 2526 2527 auto pos = indexOf(txt, "<Folder"); 2528 if(pos < 0) 2529 return; 2530 auto pos2 = indexOf(txt[pos .. $], '\n'); 2531 if(pos < 0) 2532 return; 2533 2534 string ins = " <Folder name=\"port\">\n"; 2535 string portdir = sdk_d_path ~ "port"; 2536 foreach (string name; dirEntries(portdir, SpanMode.shallow)) 2537 if (globMatch(baseName(name), "*.d")) 2538 ins ~= " <File path=\"port\\" ~ baseName(name) ~ "\" />\n"; 2539 2540 string folder = "port"; 2541 2542 string[] files = split(sources); 2543 foreach(file; files) 2544 { 2545 if(file == "\\" || file == "SRC" || file == "=") 2546 continue; 2547 string dir = dirName(file); 2548 if(dir != folder) 2549 { 2550 ins ~= " </Folder>\n"; 2551 ins ~= " <Folder name=\"" ~ dir ~ "\">\n"; 2552 folder = dir; 2553 } 2554 ins ~= " <File path=\"" ~ file ~ "\" />\n"; 2555 } 2556 ins ~= " </Folder>\n"; 2557 ins ~= " </Folder>\n"; 2558 ins ~= "</DProject>\n"; 2559 string xml = txt[0 .. pos + pos2 + 1] ~ ins; 2560 if (xml != txt) 2561 std.file.write(projfile, xml); 2562 } 2563 2564 void setCurrentFile(string file) 2565 { 2566 currentFile = file; 2567 2568 currentFullModule = fixImport(file); 2569 auto p = lastIndexOf(currentFullModule, '.'); 2570 if(p >= 0) 2571 currentModule = currentFullModule[p+1 .. $]; 2572 else 2573 currentModule = currentFullModule; 2574 2575 addedImports = addedImports.init; 2576 currentImports = currentImports.init; 2577 2578 string[string] reinit; 2579 tokImports = reinit; // tokImports.init; dmd bugzilla #3491 2580 } 2581 2582 int main(string[] argv) 2583 { 2584 if(argv.length <= 1) 2585 { 2586 writeln("usage: ", baseName(argv[0]), " {-vsi|-dte|-win|-sdk|-prefix|-verbose|-define} [files...]"); 2587 writeln(); 2588 writeln(" -vsi=DIR specify path to Visual Studio Integration SDK"); 2589 writeln(" -dte=DIR specify path to additional IDL files from VSI SDK"); 2590 writeln(" -win=DIR specify path to Windows SDK include folder"); 2591 writeln(" -sdk=DIR output base directory for Windows/VSI SDK files"); 2592 writeln(" -prefix=P prefix used for identifiers that are D keywords"); 2593 writeln(" -verbose report undefined definitions in preprocessor conditions"); 2594 writeln(); 2595 writeln("Example: ", baseName(argv[0]), ` test.idl`); 2596 writeln(" ", baseName(argv[0]), ` -win="%WindowsSdkDir%\Include" -vsi="%VSSDK110Install%" -sdk=sdk`); 2597 return -1; 2598 } 2599 2600 getopt(argv, 2601 "vsi", &vsi_base_path, 2602 "dte", &dte_path, 2603 "win", &win_path, 2604 "sdk", &sdk_d_path, 2605 "prefix", &keywordPrefix, 2606 "verbose", &verbose); 2607 2608 dte_path = replace(dte_path, "/", "\\"); 2609 win_path = replace(win_path, "/", "\\"); 2610 sdk_d_path = replace(sdk_d_path, "/", "\\"); 2611 if(!dte_path.empty && !_endsWith(dte_path, "\\")) 2612 dte_path ~= "\\"; 2613 if(!win_path.empty && !_endsWith(win_path, "\\")) 2614 win_path ~= "\\"; 2615 if(!sdk_d_path.empty && !_endsWith(sdk_d_path, "\\")) 2616 sdk_d_path ~= "\\"; 2617 2618 if(!vsi_base_path.empty) 2619 { 2620 vsi_path = vsi_base_path ~ r"\VisualStudioIntegration\Common\IDL\"; 2621 vsi_hpath = vsi_base_path ~ r"\VisualStudioIntegration\Common\Inc\"; 2622 } 2623 if(!sdk_d_path.empty) 2624 { 2625 vsi_d_path = sdk_d_path ~ dirVSI ~ r"\"; 2626 win_d_path = sdk_d_path ~ dirWin ~ r"\"; 2627 } 2628 2629 initFiles(); 2630 2631 // GC.disable(); 2632 2633 disabled_defines["__VARIANT_NAME_1"] = 1; 2634 disabled_defines["__VARIANT_NAME_2"] = 1; 2635 disabled_defines["__VARIANT_NAME_3"] = 1; 2636 disabled_defines["__VARIANT_NAME_4"] = 1; 2637 disabled_defines["uuid_constant"] = 1; 2638 2639 // declared twice 2640 disabled_defines["VBProjectProperties2"] = 1; 2641 disabled_defines["VBProjectConfigProperties2"] = 1; // declared twice 2642 disabled_defines["IID_ProjectProperties2"] = 1; 2643 disabled_defines["IID_ProjectConfigurationProperties2"] = 1; 2644 // bad init 2645 disabled_defines["DOCDATAEXISTING_UNKNOWN"] = 1; 2646 disabled_defines["HIERARCHY_DONTCHANGE"] = 1; 2647 disabled_defines["SELCONTAINER_DONTCHANGE"] = 1; 2648 disabled_defines["HIERARCHY_DONTPROPAGATE"] = 1; 2649 disabled_defines["SELCONTAINER_DONTPROPAGATE"] = 1; 2650 disabled_defines["ME_UNKNOWN_MENU_ITEM"] = 1; 2651 disabled_defines["ME_FIRST_MENU_ITEM"] = 1; 2652 2653 // win sdk 2654 disabled_defines["pascal"] = 1; 2655 disabled_defines["WINBASEAPI"] = 1; 2656 disabled_defines["WINADVAPI"] = 1; 2657 disabled_defines["FORCEINLINE"] = 1; 2658 //disabled_defines["POINTER_64"] = 1; 2659 disabled_defines["UNALIGNED"] = 1; 2660 disabled_defines["RESTRICTED_POINTER"] = 1; 2661 disabled_defines["RTL_CONST_CAST"] = 1; 2662 disabled_defines["RTL_RUN_ONCE_INIT"] = 1; 2663 disabled_defines["RTL_SRWLOCK_INIT"] = 1; 2664 disabled_defines["RTL_CONDITION_VARIABLE_INIT"] = 1; 2665 2666 // commctrl.h 2667 disabled_defines["HDM_TRANSLATEACCELERATOR"] = 1; 2668 2669 foreach(string file; argv[1..$]) 2670 addSources(file); 2671 2672 writeln("Searching files..."); 2673 if(!win_path.empty) 2674 foreach(pat; win_idl_files) 2675 addSources(win_path ~ pat); 2676 if(!vsi_path.empty) 2677 foreach(pat; vsi_idl_files) 2678 addSources(vsi_path ~ pat); 2679 if(!vsi_hpath.empty) 2680 foreach(pat; vsi_h_files) 2681 addSources(vsi_hpath ~ pat); 2682 if(!dte_path.empty) 2683 foreach(pat; dte_idl_files) 2684 addSources(dte_path ~ pat); 2685 2686 writeln("Scanning files..."); 2687 Source[] srcs; 2688 foreach(string file; srcfiles) 2689 { 2690 Source src = new Source; 2691 src.filename = file; 2692 src.text = fromMBSz (cast(immutable(char)*)(cast(char[]) read(file) ~ "\0").ptr); 2693 try 2694 { 2695 // bad qquoting in VS2019 SDK 2696 if (file.endsWith("vsshell100.idl")) 2697 src.text = src.text.replace(`(\"VSProjectLoadPriority is deprecated\")`, `("VSProjectLoadPriority is deprecated")`); 2698 if (file.endsWith("vsshell150.idl")) 2699 src.text = src.text.replace(`(\"VSSOLUTIONDEFERREDLOADOPTION is deprecated\")`, `("VSSOLUTIONDEFERREDLOADOPTION is deprecated")`); 2700 src.tokens = scanText(src.text, 1, true); 2701 } 2702 catch(Exception e) 2703 { 2704 e.msg = file ~ e.msg; 2705 throw e; 2706 } 2707 collectClasses(src.tokens); 2708 srcs ~= src; 2709 } 2710 classes["IUnknown"] = true; 2711 classes["IServiceProvider"] = true; 2712 2713 writeln("Converting files..."); 2714 string sources = "SRC = \\\n"; 2715 foreach(Source src; srcs) 2716 { 2717 string d_file; 2718 d_file = replace(src.filename, win_path, win_d_path); 2719 d_file = replace(d_file, vsi_path, vsi_d_path); 2720 d_file = replace(d_file, vsi_hpath, vsi_d_path); 2721 d_file = replace(d_file, dte_path, vsi_d_path); 2722 d_file = toLower(d_file); 2723 if(d_file._endsWith(".idl") || d_file._endsWith(".idh")) 2724 d_file = d_file[0 .. $-3] ~ "d"; 2725 if(d_file.endsWith(".h")) 2726 d_file = d_file[0 .. $-1] ~ "d"; 2727 d_file = translateFilename(d_file); 2728 setCurrentFile(d_file); 2729 2730 writeln(src.filename, " -> ", d_file); 2731 2732 string text = convertText(src.tokens); 2733 text = removeDuplicateEmptyLines(text); 2734 2735 string hdr = makehdr(src.filename, d_file); 2736 std.file.write(d_file, toUTF8(hdr ~ text)); 2737 sources ~= "\t" ~ d_file[sdk_d_path.length .. $] ~ " \\\n"; 2738 } 2739 sources ~= "\n"; 2740 if(!sdk_d_path.empty) 2741 { 2742 version(vsi) 2743 string srcfile = sdk_d_path ~ "\\vsi_sources"; 2744 else 2745 string srcfile = sdk_d_path ~ "\\sources"; 2746 std.file.write(srcfile, sources); 2747 rewrite_vsiproject(sources); 2748 } 2749 return 0; 2750 } 2751 2752 bool verbose; 2753 bool simple = true; 2754 2755 string[] srcfiles; 2756 string[] excludefiles; 2757 string currentFile; 2758 string currentModule; 2759 string currentFullModule; 2760 } 2761 2762 /////////////////////////////////////////////////////////////////////// 2763 void testConvert(string txt, string exptxt, string mod = "") 2764 { 2765 txt = replace(txt, "\r", ""); 2766 exptxt = replace(exptxt, "\r", ""); 2767 2768 idl2d inst = new idl2d; 2769 inst.currentModule = mod; 2770 TokenList tokens = scanText(txt, 1, true); 2771 string ntxt = inst.convertText(tokens); 2772 assert(ntxt == exptxt); 2773 } 2774 2775 unittest 2776 { 2777 string txt = q{ 2778 typedef struct tag { } TAG; 2779 }; 2780 2781 string exptxt = q{ 2782 struct tag 2783 { 2784 } 2785 alias tag TAG; 2786 }; 2787 2788 testConvert(txt, exptxt); 2789 } 2790 2791 unittest 2792 { 2793 string txt = q{ 2794 cpp_quote("//;end_internal") 2795 cpp_quote("typedef struct tagELEMDESC {") 2796 cpp_quote(" TYPEDESC tdesc; /* the type of the element */") 2797 cpp_quote(" union {") 2798 cpp_quote(" IDLDESC idldesc; /* info for remoting the element */") 2799 cpp_quote(" PARAMDESC paramdesc; /* info about the parameter */") 2800 cpp_quote(" };") 2801 cpp_quote("} ELEMDESC, * LPELEMDESC;") 2802 }; 2803 2804 string exptxt = q{ 2805 //;end_internal 2806 struct tagELEMDESC 2807 { 2808 TYPEDESC tdesc; /* the type of the element */ 2809 union { 2810 IDLDESC idldesc; /* info for remoting the element */ 2811 PARAMDESC paramdesc; /* info about the parameter */ 2812 }; 2813 } 2814 alias tagELEMDESC ELEMDESC; alias tagELEMDESC * LPELEMDESC; 2815 }; 2816 2817 testConvert(txt, exptxt); 2818 } 2819 2820 /////////////////////////////////////////////////////////////////////// 2821 unittest 2822 { 2823 string txt = q{ 2824 int x; 2825 cpp_quote("#ifndef WIN16") 2826 typedef struct tagSIZE 2827 { 2828 LONG cx; 2829 LONG cy; 2830 } SIZE, *PSIZE, *LPSIZE; 2831 cpp_quote("#else // WIN16") 2832 cpp_quote("typedef struct tagSIZE") 2833 cpp_quote("{") 2834 cpp_quote(" INT cx;") 2835 cpp_quote(" INT cy;") 2836 cpp_quote("} SIZE, *PSIZE, *LPSIZE;") 2837 cpp_quote("#endif // WIN16") 2838 }; 2839 2840 version(remove_pp) 2841 string exptxt = q{ 2842 int x; 2843 struct tagSIZE 2844 { 2845 LONG cx; 2846 LONG cy; 2847 } 2848 alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; } ~ q{ 2849 // WIN16 2850 }; 2851 else // !remove_pp 2852 string exptxt = q{ 2853 int x; 2854 version(all) /* #ifndef WIN16 */ { 2855 struct tagSIZE 2856 { 2857 LONG cx; 2858 LONG cy; 2859 } 2860 alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; 2861 } else { // #else // WIN16 2862 struct tagSIZE 2863 { 2864 INT cx; 2865 INT cy; 2866 } 2867 alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; 2868 } // #endif // WIN16 2869 }; 2870 testConvert(txt, exptxt); 2871 } 2872 2873 /////////////////////////////////////////////////////////////////////// 2874 unittest 2875 { 2876 string txt = " 2877 int x; 2878 #if defined(MIDL_PASS) 2879 typedef struct _LARGE_INTEGER { 2880 #else // MIDL_PASS 2881 typedef union _LARGE_INTEGER { 2882 struct { }; 2883 #endif //MIDL_PASS 2884 LONGLONG QuadPart; 2885 } LARGE_INTEGER; 2886 "; 2887 string exptxt = " 2888 int x; 2889 union _LARGE_INTEGER 2890 { 2891 struct { }; LONGLONG QuadPart; 2892 } 2893 alias _LARGE_INTEGER LARGE_INTEGER; 2894 "; 2895 testConvert(txt, exptxt, "winnt"); 2896 } 2897 2898 /////////////////////////////////////////////////////////////////////// 2899 unittest 2900 { 2901 string txt = " 2902 #define convert() \\ 2903 hello 2904 #define noconvert(n,m) \\ 2905 hallo1 |\\ 2906 hallo2 2907 "; 2908 string exptxt = " 2909 int convert() { return " ~ " 2910 hello; } 2911 // #define noconvert(n,m) \\ 2912 // hallo1 |\\ 2913 // hallo2 2914 "; 2915 version(macro2template) exptxt = replace(exptxt, "int", "auto"); 2916 testConvert(txt, exptxt); 2917 } 2918 2919 2920 unittest 2921 { 2922 string txt = " 2923 #define CONTEXT_i386 0x00010000L // this assumes that i386 and 2924 #define CONTEXT_CONTROL (CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP 2925 "; 2926 string exptxt = " 2927 enum CONTEXT_i386 = 0x00010000; // this assumes that i386 and 2928 enum CONTEXT_CONTROL = (CONTEXT_i386 | 0x00000001); // SS:SP, CS:IP, FLAGS, BP 2929 "; 2930 testConvert(txt, exptxt); 2931 } 2932 2933 unittest 2934 { 2935 string txt = " 2936 #define NtCurrentTeb() ((struct _TEB *)_rdtebex()) 2937 "; 2938 string exptxt = " 2939 _TEB* NtCurrentTeb() { return ( cast( _TEB*)_rdtebex()); } 2940 "; 2941 version(macro2template) exptxt = replace(exptxt, "_TEB* ", "auto "); 2942 testConvert(txt, exptxt); 2943 } 2944 2945 unittest 2946 { 2947 string txt = " 2948 enum { prjBuildActionNone } 2949 cpp_quote(\"#define prjBuildActionMin prjBuildActionNone\") 2950 cpp_quote(\"#define prjBuildActionMax prjBuildActionCustom\") 2951 "; 2952 string exptxt = " 2953 enum { prjBuildActionNone } 2954 enum prjBuildActionMin = prjBuildActionNone; 2955 alias prjBuildActionEmbeddedResource prjBuildActionMax; 2956 "; 2957 testConvert(txt, exptxt); 2958 } 2959 2960 unittest 2961 { 2962 string txt = " 2963 #define _INTEGRAL_MAX_BITS 64 2964 #if (!defined (_MAC) && (!defined(MIDL_PASS) || defined(__midl)) && (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64))) 2965 typedef __int64 LONGLONG; 2966 #endif 2967 "; 2968 string exptxt = " 2969 alias long LONGLONG; 2970 "; 2971 // testConvert(txt, exptxt); 2972 } 2973 2974 unittest 2975 { 2976 string txt = " 2977 #define KEY_READ ((STANDARD_RIGHTS_READ |\\ 2978 KEY_QUERY_VALUE)\\ 2979 & (~SYNCHRONIZE)) 2980 "; 2981 string exptxt = " 2982 enum KEY_READ = ((STANDARD_RIGHTS_READ | 2983 KEY_QUERY_VALUE) 2984 & (~SYNCHRONIZE)); 2985 "; 2986 testConvert(txt, exptxt); 2987 } 2988 2989 unittest 2990 { 2991 string txt = " 2992 #if _WIN32_WINNT >= 0x0600 2993 #define _PROPSHEETPAGEA_V3 _PROPSHEETPAGEA 2994 #elif (_WIN32_IE >= 0x0400) 2995 #define _PROPSHEETPAGEA_V2 _PROPSHEETPAGEA 2996 #else 2997 #define _PROPSHEETPAGEA_V1 _PROPSHEETPAGEA 2998 #endif 2999 "; 3000 string exptxt = " 3001 version(all) /* #if _WIN32_WINNT >= 0x0600 */ { 3002 alias _PROPSHEETPAGEA_V3 _PROPSHEETPAGEA; 3003 } else version(all) /* #elif (_WIN32_IE >= 0x0400) */ { 3004 alias _PROPSHEETPAGEA_V2 _PROPSHEETPAGEA; 3005 } else { 3006 3007 alias _PROPSHEETPAGEA_V1 _PROPSHEETPAGEA; 3008 } " ~ " 3009 3010 "; 3011 testConvert(txt, exptxt, "prsht"); 3012 } 3013 3014 unittest 3015 { 3016 string txt = " 3017 #define PtrToPtr64( p ) ((void * POINTER_64) p) 3018 __inline 3019 void * POINTER_64 PtrToPtr64(const void *p) 3020 { 3021 return((void * POINTER_64) (unsigned __int64) (ULONG_PTR)p ); 3022 } 3023 "; 3024 string exptxt = " 3025 // #define PtrToPtr64( p ) ((void * POINTER_64) p) 3026 /*__inline*/ 3027 void * PtrToPtr64(const( void)*p) 3028 { 3029 return( cast(void*) cast(ulong)cast(ULONG_PTR)p ); 3030 } 3031 "; 3032 testConvert(txt, exptxt, "prsht"); 3033 } 3034 3035 unittest 3036 { 3037 string txt = "int x[3];"; 3038 string exptxt = "int[3] x;"; 3039 3040 testConvert(txt, exptxt); 3041 } 3042 3043 unittest 3044 { 3045 string txt = "struct __declspec(deprecated(\"deprecated\")) S;\n"; 3046 string exp = "/+ struct /+__declspec(deprecated(\"deprecated\"))+/ S; +/\n"; 3047 3048 testConvert(txt, exp); 3049 }