private void readResponse(ByteIngest mainResponse) throws IOException, DecompileException {
		mainResponse.clear();
		readToResponse();
		int type = readToBurst();
		int commandId;
		ByteIngest currentResponse = null;

		while (type != 7) {
			switch (type) {
				case 4:
					readQueryParam(paramDecoder);
					try {
						commandId = paramDecoder.openElement();
						switch (commandId) {
							case COMMAND_ISNAMEUSED:
								isNameUsed();
								break;
							case COMMAND_GETBYTES:
								getBytes();						// getBytes
								break;
							case COMMAND_GETCOMMENTS:
								getComments();
								break;
							case COMMAND_GETCALLFIXUP:
								getPcodeInject(InjectPayload.CALLFIXUP_TYPE);
								break;
							case COMMAND_GETCALLOTHERFIXUP:
								getPcodeInject(InjectPayload.CALLOTHERFIXUP_TYPE);
								break;
							case COMMAND_GETCALLMECH:
								getPcodeInject(InjectPayload.CALLMECHANISM_TYPE);
								break;
							case COMMAND_GETPCODEEXECUTABLE:
								getPcodeInject(InjectPayload.EXECUTABLEPCODE_TYPE);
								break;
							case COMMAND_GETCPOOLREF:
								getCPoolRef();
								break;
							case COMMAND_GETEXTERNALREF:
								getExternalRef();
								break;
							case COMMAND_GETMAPPEDSYMBOLS:
								getMappedSymbols();
								break;
							case COMMAND_GETNAMESPACEPATH:
								getNamespacePath();
								break;
							case COMMAND_GETPCODE:
								getPcode();
								break;
							case COMMAND_GETREGISTER:
								getRegister();
								break;
							case COMMAND_GETREGISTERNAME:
								getRegisterName();
								break;
							case COMMAND_GETSTRINGDATA:
								getStringData();
								break;
							case COMMAND_GETCODELABEL:
								getCodeLabel();
								break;
							case COMMAND_GETDATATYPE:
								getDataType();
								break;
							case COMMAND_GETTRACKEDREGISTERS:
								getTrackedRegisters();
								break;
							case COMMAND_GETUSEROPNAME:
								getUserOpName();
								break;
							default:
								throw new Exception("Unsupported decompiler query");
						}
					}
					catch (Exception e) { // Catch ANY exception query generates
						// and pass it down to decompiler
						write(exception_start);
						String extype = e.getClass().getName();
						String msg = e.getMessage();
						if (msg == null) {
							msg = "";
						}
						writeString(extype);
						writeString(msg);
						write(exception_end);

						if (disposestate == DisposeState.NOT_DISPOSED) {
							Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
						}
					}
					nativeOut.flush(); // Make sure decompiler receives response
					readToBurst(); // Read query terminator
					break;
				case 6:
					throw new IOException("GHIDRA/decompiler out of alignment");
				case 10:
					generateException();
					break;
				case 14:			// Start of the main decompiler output
					if (currentResponse != null) {
						throw new IOException("Nested decompiler output");
					}
					// Allocate storage buffer for the result, which is generally not tiny. So we
					// start with any initial allocation of 1024 bytes, also give an absolute upper bound
					// determined by maxResultSizeMBYtes
					currentResponse = mainResponse;
					currentResponse.open(maxResultSizeMBYtes << 20, programSource);
					break;
				case 15:			// This is the end of the main decompiler output
					if (currentResponse == null) {
						throw new IOException("Mismatched string header");
					}
					currentResponse.endIngest();
					currentResponse = null;		// Reset current buffer as a native message may follow
					break;
				case 16:			// Beginning of any native message from the decompiler
					if (currentResponse != null) {	// Beginning of native message before end of main response
						currentResponse.clear();	// Don't try to parse main response
					}
					currentResponse = stringDecoder;
					currentResponse.open(1 << 20, programSource);
					break;
				case 17:			// End of the native message from the decompiler
					if (currentResponse == null) {
						throw new IOException("Mismatched message header");
					}
					currentResponse.endIngest();
					callback.setNativeMessage(currentResponse.toString());
					currentResponse = null;
					break;
				default:
					throw new IOException("GHIDRA/decompiler alignment error");

			}
			if (currentResponse == null) {
				type = readToBurst();
			}
			else {
				type = readToBuffer(currentResponse);
			}
		}
	}
Class for communicating with a single decompiler process.
The process controls decompilation for a single Program.
The process is initiated by the registerProgram method.
If the process is ready, the statusGood flag will be set
to true.  This flag must be checked via the isReady method
prior to invoking any of the public methods.  If the
process isn't ready, the only way to recover is by
reissuing the registerProgram call and making any other
necessary initialization calls.
Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java