public static MDTypeInfo parseSpecialHandlingFunction(MDMang dmang, int rttiNum)
			throws MDException {
		MDTypeInfo typeInfo;
		char ch = dmang.getAndIncrement();
		switch (ch) {
			// UINFO: (0-5) isFunction, isMember, isvtordisp (0-5)
			// UINFO: val%2==0: near; val%2==1: far;
			case '0':
			case '1':
				typeInfo = new MDVtordisp(dmang);
				typeInfo.setPrivate();
				// When considering code '0' to be at index 0, then for this and other processing
				// below, those that have an *even* index are *near* pointers and those with
				// an *odd* index are *far* pointers
				typeInfo.setPointerFormat(
					((ch - '0') % 2 == 0) ? PointerFormat._NEAR : PointerFormat._FAR);
				break;
			case '2':
			case '3':
				typeInfo = new MDVtordisp(dmang);
				typeInfo.setProtected();
				typeInfo.setPointerFormat(
					((ch - '0') % 2 == 0) ? PointerFormat._NEAR : PointerFormat._FAR);
				break;
			case '4':
			case '5':
				typeInfo = new MDVtordisp(dmang);
				typeInfo.setPublic();
				typeInfo.setPointerFormat(
					((ch - '0') % 2 == 0) ? PointerFormat._NEAR : PointerFormat._FAR);
				break;
			case '$':
				char ch2 = dmang.getAndIncrement();
				switch (ch2) {
					case 'J':
					case 'N':
					case 'O':
					// TODO: we have J, N, O--not sure which is which:
					// UINFO: CManagedILFunction
					// UINFO: CManagedILDLLImportData
					// UINFO: CManagedNativeDLLImportData
					{
						//// Skip past '0' through '9' encoding of 0 - 9 additional
						//// characters.
						char c;
						c = dmang.getAndIncrement();
						if (c < '0' || c > '9') {
							throw new MDException(
								"Access Level 'extern \"C\"' count is wrong: " + c);
						}
						int cnt = c - '0';
						while (cnt-- > 0) {
							c = dmang.getAndIncrement();
						}
					}
						typeInfo = MDTypeInfoParser.parse(dmang, rttiNum);
						typeInfo.setExternC();
						break;
					// TODO: we have F, H, Q--not sure which is which:
					// TODO: L and M are also parsed
					// UINFO: CPPManagedILFunction
					// UINFO: CPPManagedILMain
					// UINFO: CPPManagedILDLLImportData
					// UINFO: CPPManagedNativeDLLImportData
					// UINFO: MGD_AppDomain
					case 'F':
					case 'H':
					case 'L':
					case 'M':
					case 'Q':
						typeInfo = MDTypeInfoParser.parse(dmang, rttiNum);
						break;
					default:
						throw new MDException("Access Level $$, unknown case: " + ch2);
				}
				typeInfo.setSpecialHandlingCode(ch2);
				break;
			// TODO: see following UINFO.
			// UINFO:
			// A=localdtor
			// B=vcall()
			// C=vdispmap
			// D=templateStaticDataMemberCtor
			// E=templateStaticDataMemberDtor
			case 'B':
				typeInfo = new MDVCall(dmang);
				break;
			case 'R':
				typeInfo = new MDVtordispex(dmang);
				char ch3 = dmang.getAndIncrement();
				switch (ch3) {
					case '0':
					case '1':
						typeInfo.setPrivate();
						break;
					case '2':
					case '3':
						typeInfo.setProtected();
						break;
					case '4':
					case '5':
						typeInfo.setPublic();
						break;
					default: // TODO: Any missing cases?
						throw new MDException("Access Level $R, unknown case: " + ch3);
				}
				break;
			case 'A': // TODO: see following UINFO.
				// UINFO: localdtor
			case 'C': // TODO: see following UINFO.
				// UINFO: vdispmap
			case 'D': // TODO: see following UINFO.
				// UINFO: templateStaticDataMemberCtor
			case 'E': // TODO: see following UINFO.
				// UINFO: E=templateStaticDataMemberDtor
			default: // TODO: Any missing cases?
				throw new MDException("Access Level $, unknown case: " + ch);
		}
		return typeInfo;
	}
This method handles MDTypeInfo that begin with the '$' character.  The method is
 a natural place to break the processing to reduce the complexity of the calling
 method's switch statement.
@param dmang The MDMang demangler control.
@param rttiNum The RTTI number currently seen in the processing (-1 if none)
@return The MDTypeInfo created for the data sequence being parsed.
@throws MDException For a host of data-driven parsing reasons.
Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/typeinfo/MDTypeInfoParser.java