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 }