From afdcf2e5516e9202394fe8a2e06bc617e85b54c7 Mon Sep 17 00:00:00 2001 From: Pawel Piech Date: Wed, 3 Mar 2010 19:39:47 +0000 Subject: [PATCH] [219202] - [variables][cdi] Variables view should use icons to represent types --- .../eclipse/cdt/dsf/gdb/GDBTypeParser.java | 580 ++++++++++++++++++ .../cdt/dsf/mi/service/MIExpressions.java | 71 ++- .../cdt/dsf/mi/service/MIVariableManager.java | 24 +- .../command/output/ExprMetaGetVarInfo.java | 18 +- 4 files changed, 668 insertions(+), 25 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/GDBTypeParser.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/GDBTypeParser.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/GDBTypeParser.java new file mode 100644 index 00000000000..b5d418f65c1 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/GDBTypeParser.java @@ -0,0 +1,580 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems 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: + * Wind River Systems - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb; + +import java.util.regex.Pattern; + +/** + * GDB Type Parser (duplicate of org.eclipse.cdt.debug.mi.core.GDBTypeParser) + * The code was lifted from: The C Programming Language + * B. W. Kernighan and D. Ritchie + * + * @since 3.0 + */ +public class GDBTypeParser { + + // GDB type parsing from whatis command + // declarator: type dcl + // type: (name)+ + // dcl: ('*' | '&')* direct-decl + // direct-dcl: '(' dcl ')' + // direct-dcl '(' ')' + // direct-dcl '[' integer ']' + // name: ([a-zA-z][0-9])+ + // integer ([0-9)+ + + final static int EOF = -1; + final static int NAME = 0; + final static int PARENS = 1; + final static int BRACKETS = 2; + + String line; + int index; + int tokenType; + String token; + String dataType; + String name; + GDBDerivedType gdbDerivedType; + GDBType genericType; + + public GDBType getGDBType() { + if (gdbDerivedType != null) { + return gdbDerivedType; + } + return genericType; + } + + public String getVariableName() { + return name; + } + + public GDBType parse(String s) { + // Sanity. + if (s == null) { + s = new String(); + } + s = Pattern.compile("\\bconst\\b").matcher(s).replaceAll(""); //$NON-NLS-1$//$NON-NLS-2$ + s = Pattern.compile("\\bvolatile\\b").matcher(s).replaceAll(""); //$NON-NLS-1$//$NON-NLS-2$ + s = s.trim(); + + // Initialize. + line = s; + index = 0; + tokenType = -1; + token = ""; //$NON-NLS-1$ + dataType = ""; //$NON-NLS-1$ + name = ""; //$NON-NLS-1$ + gdbDerivedType = null; + genericType = null; + + // Fetch the datatype. + while (getToken() == NAME) { + dataType += " " + token; //$NON-NLS-1$ + } + + // Hack for GDB, the typename can be something like + // class A : public B, C { ... } * + // We are only interested in "class A" + // Carefull for class A::data or class ns::A + int column = dataType.indexOf(':'); + while (column > 0) { + if ((column + 2) < dataType.length() && dataType.charAt(column + 1) == ':') { + column = dataType.indexOf(':', column+2); + continue; + } + dataType = dataType.substring(0, column); + break; + } + genericType = new GDBType(dataType); + + // Start the recursive parser. + dcl(tokenType); + return getGDBType(); + } + + public static String unParse (GDBType gdbType) { + + StringBuffer sb = new StringBuffer(); + // Fetch the datatype. + while (gdbType != null) { + GDBDerivedType derived = null; + int type = gdbType.getType(); + if (gdbType instanceof GDBDerivedType) { + derived = (GDBDerivedType)gdbType; + gdbType = derived.getChild(); + // respect the precedence of operators. + if (type == GDBType.FUNCTION) { + sb.append("()"); //$NON-NLS-1$ + } else if (type == GDBType.ARRAY) { + sb.append('[').append(derived.getDimension()).append(']'); + } else if (type == GDBType.POINTER) { + int childType = (gdbType != null) ? gdbType.getType() : GDBType.GENERIC; + if (childType == GDBType.POINTER || childType == GDBType.REFERENCE) { + sb.append('*'); + } else if (childType == GDBType.GENERIC) { + sb.insert(0, '*'); + } else { + sb.insert(0, "(*").append(')'); //$NON-NLS-1$ + } + } else if (type == GDBType.REFERENCE) { + int childType = (gdbType != null) ? gdbType.getType() : GDBType.GENERIC; + if (childType == GDBType.POINTER || childType == GDBType.REFERENCE) { + sb.append("&"); //$NON-NLS-1$ + } else if (childType == GDBType.GENERIC) { + sb.insert(0, '&'); + } else { + sb.insert(0, "(&").append(')'); //$NON-NLS-1$ + } + } + } else { + sb.insert(0, ' '); + sb.insert(0, gdbType.nameType); + gdbType = null; + } + } + return sb.toString().trim(); + + } + + public class GDBType { + public final static int GENERIC = 0; + public final static int POINTER = 1; + public final static int REFERENCE = 2; + public final static int ARRAY = 3; + public final static int FUNCTION = 4; + + String nameType; + int type; + + public GDBType(String n) { + this(n, 0); + } + + public GDBType(int t) { + this("", t); //$NON-NLS-1$ + } + + public GDBType(String n, int t) { + nameType = n; + type = t; + } + + public String toString() { + return unParse(this); + } + + public String verbose() { + return nameType; + } + + public int getType() { + return type; + } + + public String getTypeName() { + return nameType; + } + } + + public class GDBDerivedType extends GDBType { + int dimension; + GDBType child; + + public GDBDerivedType(GDBType c, int i) { + this(c, i, 0); + } + + public GDBDerivedType(GDBType c, int t, int dim) { + super(t); + setChild(c); + dimension = dim; + } + + public int getDimension() { + return dimension; + } + + public void setChild(GDBType c) { + child = c; + } + + public GDBType getChild() { + return child; + } + + public boolean hasChild() { + return child != null; + } + + public String verbose() { + StringBuffer sb = new StringBuffer(); + switch (getType()) { + case FUNCTION : + sb.append(" function returning " + (hasChild() ? child.verbose() : "")); //$NON-NLS-1$//$NON-NLS-2$ + break; + case ARRAY : + sb.append(" array[" + dimension + "]" + " of " + (hasChild() ? child.verbose() : "")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + break; + case REFERENCE : + sb.append(" reference to " + (hasChild() ? child.verbose() : "")); //$NON-NLS-1$//$NON-NLS-2$ + break; + case POINTER : + sb.append(" pointer to " + (hasChild() ? child.verbose() : "")); //$NON-NLS-1$//$NON-NLS-2$ + break; + } + return sb.toString(); + } + } + + int getch() { + if (index >= line.length() || index < 0) { + return EOF; + } + return line.charAt(index++); + } + + void ungetch() { + if (index > 0) { + index--; + } + } + + // check if the character is an alphabet + boolean isCIdentifierStart(int c) { + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || c == ':' || c == ',') { + return true; + } + return false; + } + + // check is the character is alpha numeric + // [a-zA-Z0-9] + // GDB hack accept ':' ',' part of the GDB hacks + // when doing ptype gdb returns "class A : public C { ..}" + boolean isCIdentifierPart(int c) { + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || c == ':') { + return true; + } + return false; + } + + boolean isCSpace(int c) { + if (c == ' ' || c == '\t' || c == '\f' || c == '\n') { + return true; + } + return false; + } + + void insertingChild(int kind) { + insertingChild(kind, 0); + } + + void insertingChild(int kind, int d) { + if (gdbDerivedType == null) { + gdbDerivedType = new GDBDerivedType(genericType, kind, d); + } else { + GDBDerivedType dType = gdbDerivedType; + GDBType gdbType = gdbDerivedType.getChild(); + while (gdbType instanceof GDBDerivedType) { + dType = (GDBDerivedType)gdbType; + gdbType = dType.getChild(); + } + gdbType = new GDBDerivedType(gdbType, kind, d); + dType.setChild(gdbType); + } + } + + // method returns the next token + int getToken() { + token = ""; //$NON-NLS-1$ + + int c = getch(); + + // Skip over any space + while (isCSpace(c)) { + c = getch(); + } + + //char character = (char) c; + + if (c == '(') { + c = getch(); + if (c == ')') { + token = "()"; //$NON-NLS-1$ + tokenType = PARENS; + } else if (isCIdentifierStart(c)) { + int i = 0; + token += (char)c; + while (i == 0 && c != ')') { + if (c == EOF) { + // Unbalanced parantheses. + break; + } + c = getch(); + token += (char)c; + if (c == '(') { + ++i; + } else if (c == ')') { + --i; + } + } + tokenType = PARENS; + } else { + ungetch(); + tokenType = '('; + } + + + + } else if (c == '[') { + while ((c = getch()) != ']' && c != EOF) { + token += (char) c; + } + tokenType = BRACKETS; + } else if (isCIdentifierStart(c)) { + StringBuffer sb = new StringBuffer(); + sb.append((char) c); + while (isCIdentifierPart((c = getch())) && c != EOF) { + sb.append((char) c); + } + if (c == '<') { + // Swallow template args in types like "class foobar : public C {..} *" + // FIXME: if the bracket is not terminate do we throw exception? + sb.append((char) c); + int count = 1; + do { + c = getch(); + if (c == '<') { + count++; + } else if (c == '>') { + count--; + } + if (c != ' ') { + sb.append((char)c); + } + } while (count > 0 && c != EOF); + } else if (c != EOF) { + ungetch(); + } + token = sb.toString(); + tokenType = NAME; + } else if (c == '{') { + // Swallow gdb sends things like "struct foobar {..} *" + // FIXME: if the bracket is not terminate do we throw exception? + int count = 1; + do { + c = getch(); + if (c == '{') { + count++; + } else if (c == '}') { + count--; + } + } while (count > 0 && c != EOF); + } else { + tokenType = c; + } + return tokenType; + } + + void dcl() { + dcl(getToken()); + } + + // parse a declarator + void dcl(int c) { + int nstar = 0; + int namp = 0; + if (c == '*') { + nstar++; + for (; getToken() == '*'; nstar++) { + } + } else if (c == '&') { + namp++; + for (; getToken() == '&'; namp++) { + } + } + dirdcl(); + while (nstar-- > 0) { + insertingChild(GDBType.POINTER); + } + while (namp-- > 0) { + insertingChild(GDBType.REFERENCE); + } + } + + // parse a direct declarator + void dirdcl() { + int type; + + if (tokenType == '(') { + dcl(); + if (tokenType != ')' /*&& name.length() > 0*/) { + // Do we throw an exception on unterminated parentheses + // It should have been handle by getToken() + return; + } + } else if (tokenType == NAME) { + // Useless we do not need the name of the variable + name = " " + token; //$NON-NLS-1$ + } else if (tokenType == PARENS) { + insertingChild(GDBType.FUNCTION); + } else if (tokenType == BRACKETS) { + int len = 0; + if (token.length() > 0) { + try { + len = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + } + insertingChild(GDBType.ARRAY, len); + } else if (tokenType == '&') { + insertingChild(GDBType.REFERENCE); + } else { + // oops bad declaration ? + return; + } + + while ((type = getToken()) == PARENS || type == BRACKETS) { + if (type == PARENS) { + insertingChild(GDBType.FUNCTION); + } else { /* BRACKETS */ + int len = 0; + if (token.length() > 0) { + try { + len = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + } + insertingChild(GDBType.ARRAY, len); + } + } + } + + public static void main(String[] args) { + + GDBTypeParser parser = new GDBTypeParser(); + + System.out.println("int *&"); //$NON-NLS-1$ + parser.parse("int *&"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (&rg)(int)"); //$NON-NLS-1$ + parser.parse("int (&rg)(int)"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (&ra)[3]"); //$NON-NLS-1$ + parser.parse("int (&rg)[3]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("struct link { int i; int j; struct link * next;} *"); //$NON-NLS-1$ + parser.parse("struct link { int i; int j; struct link * next} *"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("class ns::link<8, ns::A> : public ns::B { int i; int j; struct link * next;} *"); //$NON-NLS-1$ + parser.parse("class ns::link<8, ns::A> : public ns::B { int i; int j; struct link * next;} *"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("char **argv"); //$NON-NLS-1$ + parser.parse("char **argv"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (*daytab)[13]"); //$NON-NLS-1$ + parser.parse("int (*daytab)[13]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int *daytab[13]"); //$NON-NLS-1$ + parser.parse("int *daytab[13]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("void *comp()"); //$NON-NLS-1$ + parser.parse("void *comp()"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("void (*comp)()"); //$NON-NLS-1$ + parser.parse("void (*comp)()"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (*func[15])()"); //$NON-NLS-1$ + parser.parse("int (*func[15])()"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("char (*(*x())[])()"); //$NON-NLS-1$ + parser.parse("char (*(*x())[])()"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("char (*(*x[3])())[5]"); //$NON-NLS-1$ + parser.parse("char (*(*x[3])())[5]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("char *[5]"); //$NON-NLS-1$ + parser.parse("char *[5]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int [2][3]"); //$NON-NLS-1$ + parser.parse("int [2][3]"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (int, char **)"); //$NON-NLS-1$ + parser.parse("int (int, char **)"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (int)"); //$NON-NLS-1$ + parser.parse("int (int)"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int (void)"); //$NON-NLS-1$ + parser.parse("int (void)"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + System.out.println("int ()"); //$NON-NLS-1$ + parser.parse("int ()"); //$NON-NLS-1$ + System.out.println(GDBTypeParser.unParse(parser.getGDBType())); + System.out.println(parser.getGDBType().verbose()); + System.out.println(); + + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java index cbe5486ae7a..189617f71d6 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java @@ -33,6 +33,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.command.CommandCache; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes; @@ -71,7 +72,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I * * @since 3.0 */ - public static final String DETAILS_FORMAT = "Details"; + public static final String DETAILS_FORMAT = "Details"; //$NON-NLS-1$ /* The order given here is the order that will be used by DSF in the Details Pane */ private static final String[] FORMATS_SUPPORTED = new String[] { @@ -322,19 +323,29 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I private final String exprType; private final int numChildren; private final boolean editable; + private final BasicType fBasicType; /** * ExpressionDMData constructor. */ public ExpressionDMData(String expr, String type, int num, boolean edit) { - relativeExpression = expr; - exprType = type; - numChildren = num; - editable = edit; + this (expr, type, num, edit, null); } + /** + * ExpressionDMData constructor. + * @since 3.0 + */ + public ExpressionDMData(String expr, String type, int num, boolean edit, BasicType basicType) { + relativeExpression = expr; + exprType = type; + numChildren = num; + editable = edit; + fBasicType = basicType; + } + public BasicType getBasicType() { - return null; + return fBasicType; } public String getEncoding() { @@ -603,16 +614,44 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I final DataRequestMonitor rm) { if (dmc instanceof MIExpressionDMC) { - fExpressionCache.execute( - new ExprMetaGetVar(dmc), - new DataRequestMonitor(getExecutor(), rm) { - @Override - protected void handleSuccess() { - rm.setData(new ExpressionDMData(getData().getExpr(), - getData().getType(), getData().getNumChildren(), getData().getEditable())); - rm.done(); - } - }); + fExpressionCache.execute( + new ExprMetaGetVar(dmc), + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + IExpressionDMData.BasicType basicType = null; + + GDBType gdbType = getData().getGDBType(); + + if (gdbType != null) { + switch (gdbType.getType()) { + case GDBType.ARRAY: + basicType = IExpressionDMData.BasicType.array; + break; + case GDBType.FUNCTION: + basicType = IExpressionDMData.BasicType.function; + break; + case GDBType.POINTER: + case GDBType.REFERENCE: + basicType = IExpressionDMData.BasicType.pointer; + break; + case GDBType.GENERIC: + default: + if (getData().getNumChildren() > 0) { + basicType = IExpressionDMData.BasicType.array; + } else { + basicType = IExpressionDMData.BasicType.basic; + } + break; + } + } + + rm.setData(new ExpressionDMData( + getData().getExpr(),getData().getType(), getData().getNumChildren(), + getData().getEditable(), basicType)); + rm.done(); + } + }); } else if (dmc instanceof InvalidContextExpressionDMC) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$ rm.done(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java index 0b4e69ca321..19c1f865bc3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java @@ -42,6 +42,8 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; import org.eclipse.cdt.dsf.debug.service.command.ICommandToken; import org.eclipse.cdt.dsf.debug.service.command.IEventListener; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.gdb.GDBTypeParser; +import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.MIExpressions.ExpressionInfo; import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC; @@ -207,6 +209,7 @@ public class MIVariableManager implements ICommandControl { // The full expression that can be used to characterize this object private String fullExp = null; private String type = null; + private GDBType gdbType; private int numChildren = 0; private Boolean editable = null; @@ -254,21 +257,21 @@ public class MIVariableManager implements ICommandControl { public String getExpression() { return fullExp; } public String getType() { return type; } + + /** @since 3.0 */ + public GDBType getGDBType() { return gdbType; } public int getNumChildren() { return numChildren; } public String getValue(String format) { return valueMap.get(format); } public ExpressionInfo[] getChildren() { return children; } - //FIX replace these methods with CDT's GDBTypeParser (see bug 200897 comment #5) - // int(*)[5] is a pointer to an array (so it is a pointer but not an array) (e.g., &b where int b[5]) - // int *[5] is an array of pointers (so it is an array but not a pointer) (e.g., int *b[5]) - public boolean isArray() { return (getType() == null) ? false : getType().endsWith("]") && !getType().contains("(*)") ; }//$NON-NLS-1$//$NON-NLS-2$ - public boolean isPointer() { return (getType() == null) ? false : getType().contains("*")&& !isArray(); }//$NON-NLS-1$ - public boolean isMethod() { return (getType() == null) ? false : getType().contains("()"); }//$NON-NLS-1$ + public boolean isArray() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.ARRAY; } + public boolean isPointer() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.POINTER; } + public boolean isMethod() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.FUNCTION; } // A complex variable is one with children. However, it must not be a pointer since a pointer has one child // according to GDB, but is still a 'simple' variable - public boolean isComplex() { return (getType() == null) ? false : getNumChildren() > 0 && !isPointer(); } + public boolean isComplex() { return (getGDBType() == null) ? false : getGDBType().getType() != GDBType.POINTER && getNumChildren() > 0; } public void setGdbName(String n) { gdbName = n; } public void setCurrentFormat(String f) { format = f; } @@ -276,6 +279,7 @@ public class MIVariableManager implements ICommandControl { public void setExpressionData(String fullExpression, String t, int num) { fullExp = fullExpression; type = t; + gdbType = fGDBTypeParser.parse(t); numChildren = num; } @@ -1324,6 +1328,11 @@ public class MIVariableManager implements ICommandControl { } } + /** + * @since 3.0 + */ + private static final GDBTypeParser fGDBTypeParser = new GDBTypeParser(); + private final DsfSession fSession; /** Provides access to the GDB/MI back-end */ @@ -1586,6 +1595,7 @@ public class MIVariableManager implements ICommandControl { exprCtx.getRelativeExpression(), getData().getNumChildren(), getData().getType(), + getData().getGDBType(), !getData().isComplex())); drm.done(); processCommandDone(token, drm.getData()); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/ExprMetaGetVarInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/ExprMetaGetVarInfo.java index 658d392864c..5196767e0cd 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/ExprMetaGetVarInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/ExprMetaGetVarInfo.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.mi.service.command.output; import org.eclipse.cdt.dsf.debug.service.command.ICommand; import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; +import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType; public class ExprMetaGetVarInfo implements ICommandResult { @@ -19,17 +20,30 @@ public class ExprMetaGetVarInfo implements ICommandResult { private final int numChild; private final String type; private final boolean editable; - - public ExprMetaGetVarInfo(String e, int n, String t, boolean edit) { + private final GDBType gdbType; + + public ExprMetaGetVarInfo(String e, int n, String t, boolean edit) { + this (e, n, t, null, edit); + } + + /** + * @since 3.0 + */ + public ExprMetaGetVarInfo(String e, int n, String t, GDBType gt, boolean edit) { expression = e; numChild = n; type = t; editable = edit; + gdbType = gt; } public String getExpr() { return expression; } public int getNumChildren() { return numChild; } public String getType() { return type; } + /** + * @since 3.0 + */ + public GDBType getGDBType() { return gdbType; } public boolean getEditable() { return editable; } public V getSubsetResult(ICommand command) {