Commit 1ce5b127 authored by Fawzi Mohamed's avatar Fawzi Mohamed
Browse files

ios: fix handling of command characters in run



Xml does not support control characters (even if encoded), thus
QXmlStreamWriter does not encode them, and QXmlStreamReader gives an
error with them.
Thus outputting a control char would stop the application.
Now we send them with a special tag and decode them.
Note that the Output pane does some emulation of terminal behavior
when receiving them.
Sending app output as block because otherwise the stange logic
within the OutputPane inserts spurious newlines (a string not
containing a newline always gets a newline prepended) .

Task-number: QTCREATORBUG-11219
Change-Id: I3557ffbb23ca2ea4eec9a97335a95580c9c4482b
Reviewed-by: default avatarEike Ziller <eike.ziller@digia.com>
Reviewed-by: default avatarFawzi Mohamed <fawzi.mohamed@digia.com>
parent 9f81e79c
......@@ -222,9 +222,9 @@ void IosDebugSupport::handleRemoteErrorOutput(const QString &output)
{
if (m_runControl) {
if (m_runControl->engine())
m_runControl->engine()->showMessage(output + QLatin1Char('\n'), AppError);
m_runControl->engine()->showMessage(output, AppError);
else
m_runControl->showMessage(output + QLatin1Char('\n'), AppError);
m_runControl->showMessage(output, AppError);
}
}
......
......@@ -62,6 +62,7 @@ struct ParserState {
Value,
QueryResult,
AppOutput,
ControlChar,
AppStarted,
InferiorPid,
GdbServerPort,
......@@ -87,9 +88,10 @@ struct ParserState {
case Status:
case InferiorPid:
case GdbServerPort:
case AppOutput:
return true;
case QueryResult:
case AppOutput:
case ControlChar:
case AppStarted:
case AppTransfer:
case Item:
......@@ -398,6 +400,13 @@ void IosToolHandlerPrivate::processXml()
stack.append(ParserState(ParserState::QueryResult));
} else if (elName == QLatin1String("app_output")) {
stack.append(ParserState(ParserState::AppOutput));
} else if (elName == QLatin1String("control_char")) {
QXmlStreamAttributes attributes = outputParser.attributes();
QChar c[1] = { QChar::fromLatin1(static_cast<char>(attributes.value(QLatin1String("code")).toString().toInt())) };
if (stack.size() > 0 && stack.last().collectChars())
stack.last().chars.append(c[0]);
stack.append(ParserState(ParserState::ControlChar));
break;
} else if (elName == QLatin1String("item")) {
stack.append(ParserState(ParserState::Item));
} else if (elName == QLatin1String("status")) {
......@@ -466,6 +475,9 @@ void IosToolHandlerPrivate::processXml()
stop(0);
return;
case ParserState::AppOutput:
appOutput(p.chars);
break;
case ParserState::ControlChar:
break;
case ParserState::AppStarted:
break;
......@@ -494,9 +506,7 @@ void IosToolHandlerPrivate::processXml()
// isCDATA() returns true.
if (stack.isEmpty())
break;
if (stack.last().kind == ParserState::AppOutput)
emit appOutput(outputParser.text().toString());
else if (stack.last().collectChars())
if (stack.last().collectChars())
stack.last().chars.append(outputParser.text());
break;
case QXmlStreamReader::Comment:
......
......@@ -65,6 +65,7 @@ public:
void writeMsg(const char *msg);
void writeMsg(const QString &msg);
void stopXml(int errorCode);
void writeTextInElement(const QString &output);
private slots:
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
const QString &info);
......@@ -338,13 +339,15 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId,
void IosTool::writeMsg(const char *msg)
{
out.writeTextElement(QLatin1String("msg"), QLatin1String(msg));
outFile.flush();
writeMsg(QString::fromLatin1(msg));
}
void IosTool::writeMsg(const QString &msg)
{
out.writeTextElement(QLatin1String("msg"), msg);
out.writeStartElement(QLatin1String("msg"));
writeTextInElement(msg);
out.writeCharacters(QLatin1String("\n"));
out.writeEndElement();
outFile.flush();
}
......@@ -366,18 +369,35 @@ void IosTool::deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::D
doExit();
}
void IosTool::writeTextInElement(const QString &output)
{
QRegExp controlCharRe(QLatin1String("[\x01-\x08]|\x0B|\x0C|[\x0E-\x1F]|\\0000"));
int pos = 0;
int oldPos = 0;
while ((pos = controlCharRe.indexIn(output, pos)) != -1) {
out.writeCharacters(output.mid(oldPos, pos - oldPos));
out.writeEmptyElement(QLatin1String("control_char"));
out.writeAttribute(QLatin1String("code"), QString::number(output.at(pos).toLatin1()));
pos += 1;
oldPos = pos;
}
out.writeCharacters(output.mid(oldPos, output.length() - oldPos));
}
void IosTool::appOutput(const QString &output)
{
if (inAppOutput)
out.writeCharacters(output);
else
out.writeTextElement(QLatin1String("app_output"), output);
if (!inAppOutput)
out.writeStartElement(QLatin1String("app_output"));
writeTextInElement(output);
if (!inAppOutput)
out.writeEndElement();
outFile.flush();
}
void IosTool::errorMsg(const QString &msg)
{
writeMsg(msg + QLatin1Char('\n'));
writeMsg(msg);
}
void IosTool::handleNewConnection()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment