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