GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
{
    packet.SetFilePos(::strlen ("QEnvironment:"));
    const uint32_t bytes_left = packet.GetBytesLeft();
    if (bytes_left > 0)
    {
        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
        return SendOKResponse ();
    }
    return SendErrorResponse (12);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("QLaunchArch:"));
  const uint32_t bytes_left = packet.GetBytesLeft();
  if (bytes_left > 0) {
    const char *arch_triple = packet.Peek();
    ArchSpec arch_spec(arch_triple, NULL);
    m_process_launch_info.SetArchitecture(arch_spec);
    return SendOKResponse();
  }
  return SendErrorResponse(13);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded (StringExtractorGDBRemote &packet)
{
    packet.SetFilePos(::strlen("QEnvironmentHexEncoded:"));
    const uint32_t bytes_left = packet.GetBytesLeft();
    if (bytes_left > 0)
    {
        std::string str;
        packet.GetHexByteString(str);
        m_process_launch_info.GetEnvironmentEntries().AppendArgument(str.c_str());
        return SendOKResponse();
    }
    return SendErrorResponse(12);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
{
    // The 'A' packet is the most over designed packet ever here with
    // redundant argument indexes, redundant argument lengths and needed hex
    // encoded argument string values. Really all that is needed is a comma
    // separated hex encoded argument value list, but we will stay true to the
    // documented version of the 'A' packet here...

    packet.SetFilePos(1); // Skip the 'A'
    bool success = true;
    while (success && packet.GetBytesLeft() > 0)
    {
        // Decode the decimal argument string length. This length is the
        // number of hex nibbles in the argument string value.
        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
        if (arg_len == UINT32_MAX)
            success = false;
        else
        {
            // Make sure the argument hex string length is followed by a comma
            if (packet.GetChar() != ',')
                success = false;
            else
            {
                // Decode the argument index. We ignore this really becuase
                // who would really send down the arguments in a random order???
                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
                if (arg_idx == UINT32_MAX)
                    success = false;
                else
                {
                    // Make sure the argument index is followed by a comma
                    if (packet.GetChar() != ',')
                        success = false;
                    else
                    {
                        // Decode the argument string value from hex bytes
                        // back into a UTF8 string and make sure the length
                        // matches the one supplied in the packet
                        std::string arg;
                        if (packet.GetHexByteString(arg) != (arg_len / 2))
                            success = false;
                        else
                        {
                            // If there are any bytes lft
                            if (packet.GetBytesLeft())
                            {
                                if (packet.GetChar() != ',')
                                    success = false;
                            }

                            if (success)
                            {
                                if (arg_idx == 0)
                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
                            }
                        }
                    }
                }
            }
        }
    }

    if (success)
    {
        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
        m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
        {
            return SendOKResponse ();
        }
    }
    return SendErrorResponse (8);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
  // The 'A' packet is the most over designed packet ever here with
  // redundant argument indexes, redundant argument lengths and needed hex
  // encoded argument string values. Really all that is needed is a comma
  // separated hex encoded argument value list, but we will stay true to the
  // documented version of the 'A' packet here...

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
  int actual_arg_index = 0;

  packet.SetFilePos(1); // Skip the 'A'
  bool success = true;
  while (success && packet.GetBytesLeft() > 0) {
    // Decode the decimal argument string length. This length is the
    // number of hex nibbles in the argument string value.
    const uint32_t arg_len = packet.GetU32(UINT32_MAX);
    if (arg_len == UINT32_MAX)
      success = false;
    else {
      // Make sure the argument hex string length is followed by a comma
      if (packet.GetChar() != ',')
        success = false;
      else {
        // Decode the argument index. We ignore this really because
        // who would really send down the arguments in a random order???
        const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
        if (arg_idx == UINT32_MAX)
          success = false;
        else {
          // Make sure the argument index is followed by a comma
          if (packet.GetChar() != ',')
            success = false;
          else {
            // Decode the argument string value from hex bytes
            // back into a UTF8 string and make sure the length
            // matches the one supplied in the packet
            std::string arg;
            if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
                (arg_len / 2))
              success = false;
            else {
              // If there are any bytes left
              if (packet.GetBytesLeft()) {
                if (packet.GetChar() != ',')
                  success = false;
              }

              if (success) {
                if (arg_idx == 0)
                  m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(),
                                                                    false);
                m_process_launch_info.GetArguments().AppendArgument(arg);
                if (log)
                  log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
                              __FUNCTION__, actual_arg_index, arg.c_str());
                ++actual_arg_index;
              }
            }
          }
        }
      }
    }
  }

  if (success) {
    m_process_launch_error = LaunchProcess();
    if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
      return SendOKResponse();
    } else {
      Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
      if (log)
        log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
                    __FUNCTION__, m_process_launch_error.AsCString());
    }
  }
  return SendErrorResponse(8);
}