static MIValue &ErrorMIValue(String const &msg) { static MIValue v; v.SetError(msg); return v; }
// read debugger output analyzing command responses and async output // things are quite tricky because debugger output seems to be // slow and we have almost no terminator to stop on -- (gdb) is not // so reliable as it can happen (strangely) in middle of nothing MIValue Gdb_MI2::ParseGdb(String const &output, bool wait) { MIValue res; // parse result data StringStream ss(output); while(!ss.IsEof()) { String s; String str = ss.GetLine(); s = str; while(str.GetCount() == 1024 && !ss.IsEof()) { str = ss.GetLine(); s << str; } s = TrimBoth(s); // check 'running' and 'stopped' async output if(s.StartsWith("*running")) { started = true; stopReason.Clear(); continue; } else if(s.StartsWith("*stopped")) { stopped = true; s = '{' + s.Mid(9) + '}'; stopReason = MIValue(s); continue; } // catch process start/stop and store/remove pids else if(s.StartsWith("=thread-group-started,id=")) { String id, pid; int i = s.Find("id="); if(i < 0) continue; i += 4; while(s[i] && s[i] != '"') id.Cat(s[i++]); i = s.Find("pid="); if(i < 0) continue; i += 5; while(s[i] && s[i] != '"') pid.Cat(s[i++]); processes.Add(id, atoi(pid)); continue; } else if(s.StartsWith("=thread-group-exited,id=")) { String id; int i = s.Find("id="); if(i < 0) continue; i += 4; while(s[i] && s[i] != '"') id.Cat(s[i++]); i = processes.Find(id); if(i >= 0) processes.Remove(i); continue; } // skip asynchronous responses // in future, we could be gather/use them if(s[0] == '*'|| s[0] == '=') continue; // here handling of command responses // we're not interested either, as we use MI interface if(s[0] == '~') continue; // here handling of target output // well, for now discard this one too, but it should go on console output if(s[0] == '~') continue; // here handling of gdb log/debug message // not interesting here if(s[0] == '&') continue; // now we SHALL have something starting with any of // // "^done", "^running", "^connected", "^error" or "^exit" records if(s.StartsWith("^done") || s.StartsWith("^running")) { // here we've got succesful command output in list form, if any // shall skip the comma; following can be a serie of pairs, // or directly an array of maps in form of : // [{key="value",key="value",...},{key="value"...}...] int i = 5; // just skip shortest, ^done while(s[i] && s[i] != ',') i++; if(!s[i]) continue; i++; if(!s[i]) continue; res = MIValue(s.Mid(i)); continue; } else if(s.StartsWith("^error")) { // first array element is reserved for command result status s = s.Right(12); // '^error,msg=\"' s = s.Left(s.GetCount() - 1); res.SetError(s); } else continue; } return res; }