//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void RequireOk(MiResultRecord resultRecord, string command) { if (resultRecord == null) { throw new ArgumentNullException("resultRecord"); } else if (!CheckOk(resultRecord)) { if (resultRecord.HasField("msg")) { string errorReason = resultRecord ["msg"] [0].GetString(); throw new InvalidOperationException(string.Format("'{0}' failed with error: {1}", command, errorReason)); } else { throw new InvalidOperationException(string.Format("'{0}' failed with unspecified error", command)); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void OnClientResultRecord (MiResultRecord resultRecord) { LoggingUtils.PrintFunction (); switch (resultRecord.Class) { case "done": case "running": // same behaviour (backward compatibility) { // // "^done" [ "," results ]: The synchronous operation was successful, results are the return values. // try { if (resultRecord.HasField ("reason")) { int stoppedIndex = resultRecord ["reason"].Count - 1; MiResultValue stoppedReason = resultRecord ["reason"] [stoppedIndex]; switch (stoppedReason.GetString ()) { case "exited": case "exited-normally": case "exited-signalled": { if (m_interruptOperationCompleted != null) { m_interruptOperationCompleted.Set (); } ThreadPool.QueueUserWorkItem (delegate (object state) { try { LoggingUtils.RequireOk (Engine.Detach (NativeProgram.DebugProgram)); } catch (Exception e) { LoggingUtils.HandleException (e); } }); break; } default: { throw new NotImplementedException (); } } } } catch (Exception e) { LoggingUtils.HandleException (e); } break; } case "connected": { // // ^connected: GDB has connected to a remote target. // try { // // If notifications are unsupported, we should assume that we need to refresh breakpoints when connected. // if (!GdbClient.GetClientFeatureSupported ("breakpoint-notifications")) { Engine.BreakpointManager.SetDirty (true); } Engine.BreakpointManager.RefreshBreakpoints (); } catch (Exception e) { LoggingUtils.HandleException (e); } break; } case "error": { // // "^error" "," c-string: The operation failed. The c-string contains the corresponding error message. // break; } case "exit": { // // ^exit: GDB has terminated. // break; } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static bool CheckOk(MiResultRecord resultRecord) { return((resultRecord != null) && (!resultRecord.IsError())); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static MiRecord ParseGdbOutputRecord(string streamOutput) { if (string.IsNullOrEmpty(streamOutput)) { return(null); } // // Process any leading 'async-record' or 'result-record' token. // int streamIndex = 0; if (streamOutput.StartsWith("(gdb)")) { // // GDB prompt. Waiting for input. // return(new MiPromptRecord()); } else if (streamOutput [streamIndex] == '~') { // // Console stream record. Clears leading '~" and trailing '\\n"' characters. // ++streamIndex; StringBuilder consoleStreamBuilder = new StringBuilder(streamOutput.Trim(new char [] { '~', '\"' })); //consoleStreamBuilder.Replace ("\\n", "\n"); return(new MiStreamRecord(MiStreamRecord.StreamType.Console, consoleStreamBuilder.ToString())); } else if (streamOutput [streamIndex] == '@') { // // Target stream record. Clears leading '@" and trailing '\\n"' characters. // ++streamIndex; StringBuilder targetStreamBuilder = new StringBuilder(streamOutput.Trim(new char [] { '@', '\"' })); //targetStreamBuilder.Replace ("\\n", "\n"); return(new MiStreamRecord(MiStreamRecord.StreamType.Target, targetStreamBuilder.ToString())); } else if (streamOutput [streamIndex] == '&') { // // Log stream record. Clears leading '&" and trailing '\\n"' characters. // ++streamIndex; StringBuilder logStreamBuilder = new StringBuilder(streamOutput.Trim(new char [] { '&', '\"' })); //logStreamBuilder.Replace ("\\n", "\n"); return(new MiStreamRecord(MiStreamRecord.StreamType.Log, logStreamBuilder.ToString())); } else { // // The following record types have associated key-pair data; identify the type and build a result collection. // string recordData = streamOutput.Substring(streamIndex); int bufferStartPos = 0; int bufferCurrentPos = bufferStartPos; char type = '^'; uint token = 0; while (bufferCurrentPos < streamOutput.Length) { if (((bufferCurrentPos + 1) >= streamOutput.Length) || (streamOutput [bufferCurrentPos + 1] == ',')) { string clazz = recordData.Substring(bufferStartPos, (bufferCurrentPos + 1) - bufferStartPos); string data = string.Empty; if (((bufferCurrentPos + 1) < streamOutput.Length) && (streamOutput [bufferCurrentPos + 1] == ',')) { data = recordData.Substring(bufferCurrentPos + 2); } MiRecord resultRecord = null; List <MiResultValue> values = new List <MiResultValue> (); try { ParseAllResults(data, ref values); } catch (Exception e) { LoggingUtils.HandleException(e); } finally { switch (type) { case '^': resultRecord = new MiResultRecord(token, clazz, values); break; case '*': resultRecord = new MiAsyncRecord(MiAsyncRecord.AsyncType.Exec, token, clazz, values); break; case '+': resultRecord = new MiAsyncRecord(MiAsyncRecord.AsyncType.Status, token, clazz, values); break; case '=': resultRecord = new MiAsyncRecord(MiAsyncRecord.AsyncType.Notify, token, clazz, values); break; } } return(resultRecord); } else if ((recordData [bufferCurrentPos] == '^') || (recordData [bufferCurrentPos] == '*') || (recordData [bufferCurrentPos] == '+') || (recordData [bufferCurrentPos] == '=')) { type = recordData [bufferCurrentPos]; string stringToken = recordData.Substring(bufferStartPos, bufferCurrentPos); if (!string.IsNullOrWhiteSpace(stringToken)) { uint.TryParse(stringToken, out token); } bufferStartPos = ++bufferCurrentPos; } ++bufferCurrentPos; } return(null); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static void RequireOk (MiResultRecord resultRecord, string command) { if (resultRecord == null) { throw new ArgumentNullException ("resultRecord"); } else if (!CheckOk (resultRecord)) { if (resultRecord.HasField ("msg")) { string errorReason = resultRecord ["msg"] [0].GetString (); throw new InvalidOperationException (string.Format ("'{0}' failed with error: {1}", command, errorReason)); } else { throw new InvalidOperationException (string.Format ("'{0}' failed with unspecified error", command)); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static bool CheckOk (MiResultRecord resultRecord) { return ((resultRecord != null) && (!resultRecord.IsError ())); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static MiRecord ParseGdbOutputRecord (string streamOutput) { if (string.IsNullOrEmpty (streamOutput)) { return null; } // // Process any leading 'async-record' or 'result-record' token. // int streamIndex = 0; if (streamOutput.StartsWith ("(gdb)")) { // // GDB prompt. Waiting for input. // return new MiPromptRecord (); } else if (streamOutput [streamIndex] == '~') { // // Console stream record. Clears leading '~" and trailing '\\n"' characters. // ++streamIndex; StringBuilder consoleStreamBuilder = new StringBuilder (streamOutput.Trim (new char [] { '~', '\"' })); //consoleStreamBuilder.Replace ("\\n", "\n"); return new MiStreamRecord (MiStreamRecord.StreamType.Console, consoleStreamBuilder.ToString ()); } else if (streamOutput [streamIndex] == '@') { // // Target stream record. Clears leading '@" and trailing '\\n"' characters. // ++streamIndex; StringBuilder targetStreamBuilder = new StringBuilder (streamOutput.Trim (new char [] { '@', '\"' })); //targetStreamBuilder.Replace ("\\n", "\n"); return new MiStreamRecord (MiStreamRecord.StreamType.Target, targetStreamBuilder.ToString ()); } else if (streamOutput [streamIndex] == '&') { // // Log stream record. Clears leading '&" and trailing '\\n"' characters. // ++streamIndex; StringBuilder logStreamBuilder = new StringBuilder (streamOutput.Trim (new char [] { '&', '\"' })); //logStreamBuilder.Replace ("\\n", "\n"); return new MiStreamRecord (MiStreamRecord.StreamType.Log, logStreamBuilder.ToString ()); } else { // // The following record types have associated key-pair data; identify the type and build a result collection. // string recordData = streamOutput.Substring (streamIndex); int bufferStartPos = 0; int bufferCurrentPos = bufferStartPos; char type = '^'; uint token = 0; while (bufferCurrentPos < streamOutput.Length) { if (((bufferCurrentPos + 1) >= streamOutput.Length) || (streamOutput [bufferCurrentPos + 1] == ',')) { string clazz = recordData.Substring (bufferStartPos, (bufferCurrentPos + 1) - bufferStartPos); string data = string.Empty; if (((bufferCurrentPos + 1) < streamOutput.Length) && (streamOutput [bufferCurrentPos + 1] == ',')) { data = recordData.Substring (bufferCurrentPos + 2); } MiRecord resultRecord = null; List<MiResultValue> values = new List<MiResultValue> (); try { ParseAllResults (data, ref values); } catch (Exception e) { LoggingUtils.HandleException (e); } finally { switch (type) { case '^': resultRecord = new MiResultRecord (token, clazz, values); break; case '*': resultRecord = new MiAsyncRecord (MiAsyncRecord.AsyncType.Exec, token, clazz, values); break; case '+': resultRecord = new MiAsyncRecord (MiAsyncRecord.AsyncType.Status, token, clazz, values); break; case '=': resultRecord = new MiAsyncRecord (MiAsyncRecord.AsyncType.Notify, token, clazz, values); break; } } return resultRecord; } else if ((recordData [bufferCurrentPos] == '^') || (recordData [bufferCurrentPos] == '*') || (recordData [bufferCurrentPos] == '+') || (recordData [bufferCurrentPos] == '=')) { type = recordData [bufferCurrentPos]; string stringToken = recordData.Substring (bufferStartPos, bufferCurrentPos); if (!string.IsNullOrWhiteSpace (stringToken)) { uint.TryParse (stringToken, out token); } bufferStartPos = ++bufferCurrentPos; } ++bufferCurrentPos; } return null; } }