/*******************************************************************************
* Copyright (c) 2011 Ericsson and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Parses the GDB "tdump" command printout, as returned by GDB, to make it a
* bit more human-friendly.
* <p>
* See bottom of this file for a raw example of what is
* returned by "tdump"
* @since 4.0
*/
public class CLITraceDumpInfo extends MIInfo {
// Here is what this pattern looks-for - the first line of the tdump printout:
//~"Data collected at tracepoint 2, trace frame 555:\n"
private static final Pattern RESULT_PATTERN_TPINFO = Pattern.compile(
"Data collected at tracepoint (\\d+), trace frame (\\d+)", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
// raw output of command
private String fOutput = null;
private String fParsedOutput = null;
// tdump parsed info
private String fTracepointNum = null;
private String fTraceFrameNumber = null;
/*
* Timestamp, if present in tracepoint frame data
* Note: not yet available in printout of command
* "tdump" -> revisit when it is.
*/
private String timestamp = null;
// keep the tdump header in parsed result or not - by default we keep
private static final boolean KEEP_HEADER = true;
/**
* Constructor.
* @param out the output of the tdump printout
*/
public CLITraceDumpInfo(MIOutput out) {
super(out);
parse(KEEP_HEADER);
}
/**
* Alternative constructor. Use this one to have control if the tdump
* header is kept or not in the result.
* @param out the output of the tdump printout
* @param keepHeader keep the tdump header in result or not
*/
public CLITraceDumpInfo(MIOutput out, boolean keepHeader) {
super(out);
parse(keepHeader);
}
/**
* Do a quick parse of the tdump printout. The tdump command printout is
* split in short pieces (records), each one wrapped like this:
* <p>
* ~"eax 0x10"
* <p>
* Also, tabs and newlines are represented by symbols: \n and \t .
* <p>
* In this method, we strip the wrapping off each record and translate the
* symbols to their value. The resulting string is not parsed further.
* <p>
* See an example of a tdump printout at the end of this file.
*/
private void parse(boolean keepHeader) {
final Pattern RESULT_PATTERN_UNWRAPRECORD = Pattern.compile("~\"(.*)\"", Pattern.CANON_EQ); //$NON-NLS-1$
StringBuffer buf = new StringBuffer();
String unwrapped;
if (isDone()) {
MIOutput out = getMIOutput();
// save raw output of command
fOutput = out.toString();
MIOOBRecord[] oobs = out.getMIOOBRecords();
for (MIOOBRecord oob : oobs) {
if (oob instanceof MIConsoleStreamOutput) {
Matcher matcher = RESULT_PATTERN_UNWRAPRECORD.matcher(oob.toString());
if (matcher.find()) {
unwrapped = matcher.group(1);
// accumulate the records into a buffer
buf.append(unwrapped);
}
}
}
// convert buffer into string
fParsedOutput = buf.toString();
// extract the tracepoint and frame numbers
Matcher matcher = RESULT_PATTERN_TPINFO.matcher(fParsedOutput);
if (matcher.find()) {
fTracepointNum = matcher.group(1).trim();
fTraceFrameNumber = matcher.group(2).trim();
}
// command result has the substrings "\n" and "\t" in it.
// replace them by their actual meaning (real newline and tab)
fParsedOutput = fParsedOutput.replaceAll("\\\\n", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
fParsedOutput = fParsedOutput.replaceAll("\\\\t+", "\t"); //$NON-NLS-1$ //$NON-NLS-2$
// Optionaly remove the header line from tdump printout
if(!keepHeader) {
fParsedOutput = fParsedOutput.replaceFirst("Data collected at tracepoint \\d+, trace frame \\d+:\\n", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
/**
* @return the raw output of tdump.
*/
public String getOutput() {
return fOutput;
}
/**
* @return a String containing the semi-parsed
* register and local variables, as listed by
* tdump.
*/
public String getContent() {
return fParsedOutput;
}
/**
* @return the tracepoint number
*/
public String getTracepointNumber() {
return fTracepointNum;
}
/**
* @return the trace's frame number
*/
public String getFrameNumber() {
return fTraceFrameNumber;
}
/**
* @return the timestamp of the tracepoint frame
*/
public String getTimestamp() {
return timestamp;
}
}
/*
* Example of raw output from command tdump:
&"tdump\n"
~"Data collected at tracepoint 2, trace frame 555:\n"
~"eax 0x10"
~"\t16"
~"\n"
~"ecx 0x0"
~"\t0"
~"\n"
~"edx 0x0"
~"\t0"
~"\n"
~"ebx 0x11"
~"\t17"
~"\n"
~"esp 0xbfec14c0"
~"\t0xbfec14c0\n"
~"ebp 0xbfec1508"
~"\t0xbfec1508\n"
~"esi 0x0"
~"\t0"
~"\n"
~"edi 0x0"
~"\t0"
~"\n"
~"eip 0x8048520"
~"\t0x8048520 <factorial1(unsigned long long)+45>\n"
~"eflags 0x216"
~"\t[ PF AF IF ]"
~"\n"
~"cs 0x73"
~"\t115"
~"\n"
~"ss 0x7b"
~"\t123"
~"\n"
~"ds 0x7b"
~"\t123"
~"\n"
~"es 0x7b"
~"\t123"
~"\n"
~"fs 0x0"
~"\t0"
~"\n"
~"gs 0x33"
~"\t51"
~"\n"
~"st0 0"
~"\t(raw 0x00000000000000000000)\n"
~"st1 0"
~"\t(raw 0x00000000000000000000)\n"
~"st2 0"
~"\t(raw 0x00000000000000000000)\n"
~"st3 0"
~"\t(raw 0x00000000000000000000)\n"
~"st4 0"
~"\t(raw 0x00000000000000000000)\n"
~"st5 0"
~"\t(raw 0x00000000000000000000)\n"
~"st6 0"
~"\t(raw 0x00000000000000000000)\n"
~"st7 0"
~"\t(raw 0x00000000000000000000)\n"
~"fctrl 0x37f"
~"\t895"
~"\n"
~"fstat 0x0"
~"\t0"
~"\n"
~"ftag 0xffff"
~"\t65535"
~"\n"
~"fiseg 0x73"
~"\t115"
~"\n"
~"fioff 0x718d9c"
~"\t7441820"
~"\n"
~"foseg 0x7b"
~"\t123"
~"\n"
~"fooff 0x754928"
~"\t7686440"
~"\n"
~"fop 0x599"
~"\t1433"
~"\n"
~"xmm0 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm1 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm2 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm3 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm4 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm5 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm6 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"xmm7 {v4_float = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_double = {0x0"
~", 0x0"
~"}"
~", v16_int8 = {0x0"
~" <repeats 16 times>}"
~", v8_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v4_int32 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v2_int64 = {0x0"
~", 0x0"
~"}"
~", uint128 = 0x00000000000000000000000000000000"
~"}"
~"\n"
~"mxcsr 0x1f80"
~"\t[ IM DM ZM OM UM PM ]"
~"\n"
~"mm0 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm1 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm2 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm3 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm4 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm5 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm6 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"mm7 {uint64 = 0x0"
~", v2_int32 = {0x0"
~", 0x0"
~"}"
~", v4_int16 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~", v8_int8 = {0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~", 0x0"
~"}"
~"}"
~"\n"
~"a = 16"
~"\n"
27^done
*/