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