Source Code Cross Referenced for AbstractVariable.java in  » IDE-Netbeans » cnd » org » netbeans » modules » cnd » debugger » gdb » models » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » cnd » org.netbeans.modules.cnd.debugger.gdb.models 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.cnd.debugger.gdb.models;
0043:
0044:        import java.beans.Customizer;
0045:        import java.beans.PropertyChangeListener;
0046:        import java.util.HashSet;
0047:        import java.util.Map;
0048:        import java.util.Set;
0049:        import java.util.logging.Level;
0050:        import java.util.logging.Logger;
0051:        import javax.swing.SwingUtilities;
0052:        import org.netbeans.api.debugger.DebuggerEngine;
0053:        import org.netbeans.api.debugger.DebuggerManager;
0054:
0055:        import org.netbeans.modules.cnd.debugger.gdb.InvalidExpressionException;
0056:        import org.netbeans.modules.cnd.debugger.gdb.Field;
0057:        import org.netbeans.modules.cnd.debugger.gdb.GdbDebugger;
0058:        import org.netbeans.modules.cnd.debugger.gdb.GdbVariable;
0059:        import org.netbeans.modules.cnd.debugger.gdb.LocalVariable;
0060:        import org.netbeans.modules.cnd.debugger.gdb.TypeInfo;
0061:        import org.netbeans.modules.cnd.debugger.gdb.utils.GdbUtils;
0062:        import org.openide.DialogDisplayer;
0063:        import org.openide.NotifyDescriptor;
0064:        import org.openide.util.NbBundle;
0065:        import org.openide.util.Utilities;
0066:
0067:        /*
0068:         * An AbstractVariable is an array, pointer, struct, or union.
0069:         *
0070:         * @author Nik Molchanov (copied from Jan Jancura's JPDA implementation)
0071:         */
0072:        public class AbstractVariable implements  LocalVariable, Customizer {
0073:
0074:            private GdbDebugger debugger;
0075:            protected String name;
0076:            protected String type;
0077:            protected String value;
0078:            protected String ovalue;
0079:            protected String derefValue;
0080:            protected Field[] fields;
0081:            protected TypeInfo tinfo;
0082:            private static Logger log = Logger.getLogger("gdb.logger"); // NOI18N
0083:
0084:            private Set<PropertyChangeListener> listeners = new HashSet<PropertyChangeListener>();
0085:
0086:            /** Create the AV from a GV. If the GV has children then create similar children for the AV */
0087:            public AbstractVariable(GdbVariable var) {
0088:                this (var.getName(), var.getValue());
0089:            }
0090:
0091:            public AbstractVariable(String name) {
0092:                this (name, null);
0093:            }
0094:
0095:            public AbstractVariable(String name, String value) {
0096:                assert name.indexOf('{') == -1; // this means a mis-parsed gdb response...
0097:                assert !Thread.currentThread().getName().equals("GdbReaderRP"); // NOI18N
0098:                assert !SwingUtilities.isEventDispatchThread();
0099:                this .name = name;
0100:                type = getDebugger().requestWhatis(name);
0101:                ovalue = null;
0102:                fields = new Field[0];
0103:                tinfo = TypeInfo.getTypeInfo(getDebugger(), this );
0104:
0105:                if (Utilities.getOperatingSystem() != Utilities.OS_MAC) {
0106:                    this .value = value;
0107:                } else {
0108:                    // Convert the Mac-specific value to standard gdb/mi format
0109:                    this .value = GdbUtils.mackHack(value);
0110:                }
0111:
0112:                if (GdbUtils.isSinglePointer(type)) {
0113:                    derefValue = getDebugger().requestValue('*' + name);
0114:                } else {
0115:                    derefValue = null;
0116:                }
0117:            }
0118:
0119:            protected AbstractVariable() {
0120:            } // used by AbstractField instantiation...
0121:
0122:            protected TypeInfo getTypeInfo() {
0123:                if (tinfo == null) {
0124:                    tinfo = TypeInfo.getTypeInfo(getDebugger(), this );
0125:                }
0126:                return tinfo;
0127:            }
0128:
0129:            protected void resetVariable() {
0130:                tinfo = null;
0131:                type = "";
0132:                value = "";
0133:                fields = new Field[0];
0134:            }
0135:
0136:            /**
0137:             * Declared type of this local.
0138:             *
0139:             * @return declared type of this local
0140:             */
0141:            public String getType() {
0142:                return type;
0143:            }
0144:
0145:            /**
0146:             * Similar to getType() except this method will wait for the type to be supplied in
0147:             * an alternate thread.
0148:             * 
0149:             * @return declared type of this local
0150:             */
0151:            public String waitForType() {
0152:                if (!SwingUtilities.isEventDispatchThread()) {
0153:                    int count = 20;
0154:
0155:                    // this can get called while var is waiting for its type to be returned
0156:                    while (type == null
0157:                            && count-- > 0
0158:                            && debugger.getState().equals(
0159:                                    GdbDebugger.STATE_STOPPED)) {
0160:                        if (log.isLoggable(Level.FINE) && count == 19) {
0161:                            log.fine("AV.waitForType: Waiting on type for "
0162:                                    + name);
0163:                        }
0164:                        try {
0165:                            Thread.sleep(100);
0166:                        } catch (InterruptedException ex) {
0167:                            return null;
0168:                        }
0169:                    }
0170:                }
0171:                return type;
0172:            }
0173:
0174:            public void setType(String type) {
0175:                this .type = type;
0176:            }
0177:
0178:            /**
0179:             * Returns string representation of type of this variable.
0180:             *
0181:             * @return string representation of type of this variable.
0182:             */
0183:            public String getValue() {
0184:                if (value.startsWith(">") && value.endsWith(".\"<")) { // NOI18N
0185:                    return '>' + value.substring(2, value.length() - 3)
0186:                            .replace("\\\"", "\"") + '<'; // NOI18N
0187:                } else {
0188:                    return value.replace("\\\"", "\""); // NOI18N
0189:                }
0190:            }
0191:
0192:            /**
0193:             * Sets string representation of value of this variable. In this case we ignore the
0194:             * request because we only allow setting values on leaves.
0195:             *
0196:             * @param value string representation of value of this variable.
0197:             */
0198:            public void setValue(String value) {
0199:                String msg = null;
0200:                String rt = getTypeInfo().getResolvedType(this );
0201:                int pos;
0202:
0203:                if (getDebugger() != null) {
0204:                    value = value.trim();
0205:                    if (value.length() > 0
0206:                            && value.charAt(0) == '('
0207:                            && (pos = GdbUtils.findMatchingParen(value, 0)) != -1) {
0208:                        // Strip a cast
0209:                        value = value.substring(pos + 1).trim();
0210:                    }
0211:                    if (rt.equals("char") || rt.equals("unsigned char")) { // NOI18N
0212:                        value = setValueChar(value);
0213:                        if (value == null) { // Invalid input
0214:                            msg = NbBundle.getMessage(AbstractVariable.class,
0215:                                    "ERR_SetValue_Invalid_Char"); // NOI18N
0216:                        }
0217:                    } else if (rt.equals("char *")
0218:                            || rt.equals("unsigned char *")) { // NOI18N
0219:                        value = setValueCharStar(value);
0220:                        if (value == null) { // Invalid input
0221:                            msg = NbBundle.getMessage(AbstractVariable.class,
0222:                                    "ERR_SetValue_Invalid_Char*"); // NOI18N
0223:                        }
0224:                    } else if ((rt.equals("int") || rt.equals("long"))) { // NOI18N
0225:                        value = setValueNumber(value);
0226:                        if (value == null) { // Invalid input
0227:                            msg = NbBundle.getMessage(AbstractVariable.class,
0228:                                    "ERR_SetValue_Invalid_Number"); // NOI18N
0229:                        }
0230:                    } else if (getDebugger().isCplusPlus() && rt.equals("bool")) { // NOI18N
0231:                        if (!value.equals("true") && !value.equals("false")
0232:                                && !isNumber(value)) { // NOI18N
0233:                            msg = NbBundle.getMessage(AbstractVariable.class,
0234:                                    "ERR_SetValue_Invalid_CplusPlus_Bool"); // NOI18N
0235:                        }
0236:                    } else if (rt.startsWith("enum ")) { // NOI18N
0237:                        value = setValueEnum(value);
0238:                        if (value == null) { // Invalid input
0239:                            msg = NbBundle.getMessage(AbstractVariable.class,
0240:                                    "ERR_SetValue_Invalid_Enum"); // NOI18N
0241:                        }
0242:                    } else if (value.charAt(0) == '"'
0243:                            || (value.startsWith("0x") && value.endsWith("\""))) { // NOI18N
0244:                        value = setValueCharStar(value);
0245:                        if (value == null) { // Invalid input
0246:                            msg = NbBundle.getMessage(AbstractVariable.class,
0247:                                    "ERR_SetValue_Invalid_Char*"); // NOI18N
0248:                        }
0249:                    } else if (GdbUtils.isPointer(rt)) {
0250:                        // no current validation
0251:                    }
0252:                    if (value != null) {
0253:                        if (value.endsWith("\\\"")) { // NOI18N
0254:                            pos = value.indexOf('"');
0255:                            if (pos != -1) {
0256:                                value = value
0257:                                        .substring(pos, value.length() - 1) + '"';
0258:                            }
0259:                        }
0260:                        if (value.charAt(0) == '(') {
0261:                            pos = GdbUtils.findMatchingParen(value, 0);
0262:                            if (pos != -1) {
0263:                                value = value.substring(pos + 1).trim();
0264:                            }
0265:                        }
0266:                    }
0267:                    if (msg == null) {
0268:                        String fullname;
0269:                        if (this  instanceof  GdbWatchVariable) {
0270:                            fullname = ((GdbWatchVariable) this ).getWatch()
0271:                                    .getExpression();
0272:                        } else {
0273:                            if (this  instanceof  AbstractField) {
0274:                                fullname = ((AbstractField) this )
0275:                                        .getFullName(false);
0276:                            } else {
0277:                                fullname = name;
0278:                            }
0279:                        }
0280:                        ovalue = this .value;
0281:                        value = getDebugger().updateVariable(fullname, value);
0282:                    }
0283:                }
0284:                if (msg != null) {
0285:                    NotifyDescriptor nd = new NotifyDescriptor.Message(msg);
0286:                    nd.setTitle("TITLE_SetValue_Warning"); // NOI18N
0287:                    DialogDisplayer.getDefault().notify(nd);
0288:                }
0289:            }
0290:
0291:            public void restoreOldValue() {
0292:                value = ovalue;
0293:            }
0294:
0295:            public synchronized void setModifiedValue(String value) {
0296:                this .value = value;
0297:                if (fields.length > 0) {
0298:                    fields = new Field[0];
0299:                    derefValue = null;
0300:                    if (value.length() > 0) {
0301:                        expandChildren();
0302:                    }
0303:                }
0304:            }
0305:
0306:            /**
0307:             * Validate the string passed to setValue. Verify its a correct char format and remove a leading
0308:             * address if needed.
0309:             *
0310:             * @param value The value typed by the user into the value editor
0311:             * @returns A valid value (valid in the sense gdb should accept it) or null
0312:             */
0313:            private String setValueChar(String value) {
0314:                int pos;
0315:
0316:                if (value.startsWith("0x") && (pos = value.indexOf(" '")) != -1
0317:                        && value.endsWith("'")) { // NOI18N
0318:                    value = value.substring(pos + 1);
0319:                } else if (value.charAt(0) == '\''
0320:                        && value.charAt(value.length() - 1) == '\'') {
0321:                    // OK
0322:                } else {
0323:                    value = null;
0324:                }
0325:                return value;
0326:            }
0327:
0328:            /**
0329:             * Validate the string passed to setValue. Verify its a correct char format and remove a leading
0330:             * address if needed.
0331:             *
0332:             * @param value The value typed by the user into the value editor
0333:             * @returns A valid value (valid in the sense gdb should accept it) or null
0334:             */
0335:            private String setValueCharStar(String value) {
0336:                int pos;
0337:
0338:                if (value.startsWith("0x")
0339:                        && (pos = value.indexOf(" \\\"")) != -1
0340:                        && value.endsWith("\\\"")) { // NOI18N
0341:                    value = '"' + value.substring(pos + 3, value.length() - 2) + '"'; // NOI18N
0342:                } else if (value.startsWith("0x")
0343:                        && (pos = value.indexOf(" \"")) != -1
0344:                        && value.endsWith("\"")) { // NOI18N
0345:                    value = value.substring(pos + 1);
0346:                } else if (value.charAt(0) == '"'
0347:                        && value.charAt(value.length() - 1) == '"') { // NOI18N
0348:                    // OK
0349:                } else {
0350:                    value = null;
0351:                }
0352:                return value;
0353:            }
0354:
0355:            /**
0356:             * Validate the string passed to setValue.
0357:             *
0358:             * @param value The value typed by the user into the value editor
0359:             * @returns A valid value (valid in the sense gdb should accept it) or null
0360:             */
0361:            private String setValueEnum(String value) {
0362:                String rt = getTypeInfo().getResolvedType(this );
0363:                int pos1 = rt.indexOf('{');
0364:                int pos2 = rt.indexOf('}');
0365:                if (pos1 > 0 && pos2 > 0) {
0366:                    String enum_values = rt.substring(pos1 + 1, pos2);
0367:                    for (String frag : enum_values.split(", ")) { // NOI18N
0368:                        if (value.equals(frag)) {
0369:                            return value;
0370:                        }
0371:                    }
0372:                }
0373:                return null;
0374:            }
0375:
0376:            /**
0377:             * Validate the string passed to setValue. Verify its a correct numerical format .
0378:             *
0379:             * @param value The value typed by the user into the value editor
0380:             * @returns A valid value (valid in the sense gdb should accept it) or null
0381:             */
0382:            private String setValueNumber(String value) {
0383:                if (isNumber(value)) {
0384:                    // OK
0385:                } else {
0386:                    value = null;
0387:                }
0388:                return value;
0389:            }
0390:
0391:            public void setObject(Object bean) {
0392:            }
0393:
0394:            /**
0395:             * See if this variable <i>will</i> have fields and should show a turner.
0396:             * We're not actually creating or counting fields here.
0397:             *
0398:             * @return 0 if the variable shouldn't have a turner and fields.length if it should
0399:             */
0400:            public int getFieldsCount() {
0401:                if (getDebugger() == null
0402:                        || !getDebugger().getState().equals(
0403:                                GdbDebugger.STATE_STOPPED)) {
0404:                    return 0;
0405:                } else if (fields.length > 0) {
0406:                    return fields.length;
0407:                } else if (mightHaveFields()) {
0408:                    return estimateFieldCount();
0409:                } else {
0410:                    return 0;
0411:                }
0412:            }
0413:
0414:            /**
0415:             * The else-if in getFieldsCount() was getting too complex, so I've factored it out and
0416:             * made it into multiple if/else-if statements. I think its easier to track this way.
0417:             * 
0418:             * @return true if the field should have a turner and false if it shouldn't
0419:             */
0420:            private boolean mightHaveFields() {
0421:                String rt = getTypeInfo().getResolvedType(this );
0422:                if (GdbUtils.isArray(rt) && !isCharString(rt)) {
0423:                    return true;
0424:                } else if (isValidPointerAddress()) {
0425:                    if (GdbUtils.isFunctionPointer(rt) || rt.equals("void *") || // NOI18N
0426:                            (isCharString(rt) && !GdbUtils.isMultiPointer(rt))) {
0427:                        return false;
0428:                    } else {
0429:                        return true;
0430:                    }
0431:                } else if (value != null && value.length() > 0
0432:                        && value.charAt(0) == '{') {
0433:                    return true;
0434:                }
0435:                return false;
0436:            }
0437:
0438:            /**
0439:             * I'd like to estimate field count based on the value string. However, this might
0440:             * actually be better. If I set the children count high then it gets reset once the
0441:             * children get created. If I set it too low, only that number of fields are shown
0442:             * (even though the var has more fields).
0443:             */
0444:            private int estimateFieldCount() {
0445:                int count = 100;
0446:                return count;
0447:            }
0448:
0449:            private boolean isValidPointerAddress() {
0450:                String frag = "";
0451:                int pos1;
0452:                long i;
0453:
0454:                if (value == null && this  instanceof  GdbWatchVariable) {
0455:                    getValue(); // A watch might not have a value yet. This will initialize "value"
0456:                }
0457:                if (value != null) { // value can be null for watches during initialization...
0458:                    if (value.length() > 0 && value.charAt(0) == '(') {
0459:                        pos1 = value.indexOf("*) 0x"); // NOI18N
0460:                        if (pos1 == -1) {
0461:                            pos1 = value.indexOf("* const) 0x"); // NOI18N
0462:                            if (pos1 != -1) {
0463:                                frag = value.substring(pos1 + 11);
0464:                            }
0465:                        } else {
0466:                            frag = value.substring(pos1 + 5);
0467:                        }
0468:                        if (pos1 != -1) {
0469:                            try {
0470:                                i = Long.parseLong(frag, 16);
0471:                            } catch (NumberFormatException ex) {
0472:                                return false;
0473:                            }
0474:                            return i > 0;
0475:                        }
0476:                    } else if (value.startsWith("0x")) { // NOI18N
0477:                        try {
0478:                            i = Long.parseLong(value.substring(2), 16);
0479:                        } catch (NumberFormatException ex) {
0480:                            return false;
0481:                        }
0482:                        return i > 0;
0483:                    }
0484:                }
0485:                return false;
0486:            }
0487:
0488:            /**
0489:             * Returns field defined in this object.
0490:             *
0491:             * @param name a name of field to be returned
0492:             * @return field defined in this object
0493:             */
0494:            public Field getField(String name) {
0495:                int i, k = fields.length;
0496:                for (i = 0; i < k; i++) {
0497:                    Field f = fields[i];
0498:                    if (name.equals(f.getName())) {
0499:                        return f;
0500:                    }
0501:                }
0502:                return null; // Not found
0503:            }
0504:
0505:            /**
0506:             * Returns all fields declared in this type that are in interval
0507:             * &lt;<code>from</code>, <code>to</code>).
0508:             */
0509:            public Field[] getFields(int from, int to) {
0510:                if (to != 0) {
0511:                    if (fields.length == 0) {
0512:                        expandChildren();
0513:                    }
0514:                    to = Math.min(fields.length, to);
0515:                    from = Math.min(fields.length, from);
0516:                    Field[] fv = new Field[to - from];
0517:                    System.arraycopy(fields, from, fv, 0, to - from);
0518:                    return fv;
0519:                }
0520:                return fields;
0521:            }
0522:
0523:            /**
0524:             * In the JPDA implementation a value isn't always a String. We're (currently)
0525:             * storing the value as a String so no conversion is done. However, keeping
0526:             * this method makes it possible for us to change at a later date...
0527:             *
0528:             * @return The value of this instance
0529:             */
0530:            public String getToStringValue() throws InvalidExpressionException {
0531:                return getValue();
0532:            }
0533:
0534:            @Override
0535:            public boolean equals(Object o) {
0536:                return o instanceof  AbstractVariable
0537:                        && getFullName(true).equals(
0538:                                ((AbstractVariable) o).getFullName(true));
0539:            }
0540:
0541:            @Override
0542:            public int hashCode() {
0543:                return name.hashCode();
0544:            }
0545:
0546:            public String getName() {
0547:                return name;
0548:            }
0549:
0550:            protected final GdbDebugger getDebugger() {
0551:                if (debugger == null) {
0552:                    DebuggerEngine currentEngine = DebuggerManager
0553:                            .getDebuggerManager().getCurrentEngine();
0554:                    if (currentEngine == null) {
0555:                        return null;
0556:                    }
0557:                    debugger = currentEngine.lookupFirst(null,
0558:                            GdbDebugger.class);
0559:                }
0560:                return debugger;
0561:            }
0562:
0563:            public synchronized boolean expandChildren() {
0564:                if (fields.length == 0) {
0565:                    createChildren();
0566:                }
0567:                return fields.length > 0;
0568:            }
0569:
0570:            private void createChildren() {
0571:                String resolvedType = getTypeInfo().getResolvedType(this );
0572:                Map<String, Object> map;
0573:                String t;
0574:                String v;
0575:
0576:                if (GdbUtils.isPointer(resolvedType)
0577:                        && !isCharString(resolvedType)
0578:                        && !GdbUtils.isMultiPointer(resolvedType)) {
0579:                    if (value.endsWith(" 0") || value.endsWith(" 0x0")) { // NOI18N
0580:                        t = null;
0581:                        v = null;
0582:                    } else {
0583:                        t = GdbUtils.getBaseType(resolvedType);
0584:                        v = getDebugger()
0585:                                .requestValue('*' + getFullName(false));
0586:                    }
0587:                } else {
0588:                    t = resolvedType;
0589:                    v = value;
0590:                }
0591:                if (v != null) { // v can be null if we're no longer in a stopped state
0592:                    if (GdbUtils.isArray(t)) {
0593:                        createChildrenForArray(t, v);
0594:                    } else if (GdbUtils.isMultiPointer(t)) {
0595:                        createChildrenForMultiPointer(t);
0596:                    } else {
0597:                        map = getTypeInfo().getMap();
0598:                        if (map != null) { // a null map means we never got type information
0599:                            if (map.isEmpty()) {
0600:                                // an empty map means its a pointer to a non-struct/class/union
0601:                                createChildrenForPointer(t, v);
0602:                            } else if (v.length() > 0) {
0603:                                String val = v.substring(1, v.length() - 1);
0604:                                int start = 0;
0605:                                int end = GdbUtils.findNextComma(val, 0);
0606:                                while (end != -1) {
0607:                                    String vfrag = val.substring(start, end)
0608:                                            .trim();
0609:                                    addField(completeFieldDefinition(this , map,
0610:                                            vfrag));
0611:                                    start = end + 1;
0612:                                    end = GdbUtils.findNextComma(val, end + 1);
0613:                                }
0614:                                addField(completeFieldDefinition(this , map, val
0615:                                        .substring(start).trim()));
0616:                            } else {
0617:                                log
0618:                                        .fine("AV.createChildren: 0 length value for "
0619:                                                + getFullName(false));
0620:                            }
0621:                        }
0622:                    }
0623:                }
0624:            }
0625:
0626:            private void createChildrenForPointer(String t, String v) {
0627:                addField(new AbstractField(this , '*' + getName(), t, v));
0628:            }
0629:
0630:            private void createChildrenForMultiPointer(String t) {
0631:                int i = 0;
0632:                String fullname = getFullName(false);
0633:                String t2 = t.substring(0, t.length() - 1);
0634:                int max_fields = t2.startsWith("char *") ? 20 : 10; // NOI18N
0635:
0636:                while (max_fields-- > 0) {
0637:                    String v = getDebugger().requestValue(
0638:                            fullname + '[' + i + ']');
0639:                    if (v == null || v.length() < 1 || v.endsWith("0x0")) { // NOI18N
0640:                        return;
0641:                    }
0642:                    addField(new AbstractField(this , getName() + '[' + i++
0643:                            + ']', t2, v));
0644:                }
0645:            }
0646:
0647:            /**
0648:             * Check the type. Does it resolve to a char *? If so then we don't want to
0649:             * expand it further. But if its not a char * then we (probably) do.
0650:             * 
0651:             * @param info The string to verify
0652:             * @return true if t is some kind of a character pointer
0653:             */
0654:            private boolean isCharString(String t) {
0655:                if (t != null && t.endsWith("*") && !t.endsWith("**")) { // NOI18N
0656:                    t = GdbUtils.getBaseType(t);
0657:                    if (t.equals("char") || t.equals("unsigned char")) { // NOI18N
0658:                        return true;
0659:                    }
0660:                }
0661:                return false;
0662:            }
0663:
0664:            /**
0665:             * Complete and create the field information. Its OK to return null because addField
0666:             * ignores it.
0667:             */
0668:            private AbstractField completeFieldDefinition(
0669:                    AbstractVariable parent, Map<String, Object> map,
0670:                    String info) {
0671:                String n, t, v;
0672:                int count;
0673:
0674:                if (info.charAt(0) == '{') { // we've got an anonymous class/struct/union...
0675:                    try {
0676:                        count = Integer.parseInt((String) map
0677:                                .get("<anon-count>")); // NOI18N
0678:                    } catch (NumberFormatException nfe) {
0679:                        count = 0;
0680:                    }
0681:                    info = info.substring(1, info.length() - 1);
0682:                    for (int i = 1; i <= count; i++) {
0683:                        @SuppressWarnings("unchecked")
0684:                        Map<String, Object> m = (Map<String, Object>) map
0685:                                .get("<anonymous" + i + ">"); // NOI18N
0686:                        int start = 0;
0687:                        int end = GdbUtils.findNextComma(info, 0);
0688:                        while (end != -1) {
0689:                            String vfrag = info.substring(start, end).trim();
0690:                            parent.addField(completeFieldDefinition(parent, m,
0691:                                    vfrag));
0692:                            start = end + 1;
0693:                            end = GdbUtils.findNextComma(info, end + 1);
0694:                        }
0695:                        parent.addField(completeFieldDefinition(parent, m, info
0696:                                .substring(start).trim()));
0697:                    }
0698:                } else {
0699:                    int pos = info.indexOf('=');
0700:                    if (pos != -1) {
0701:                        if (info.charAt(0) == '<') {
0702:                            n = NbBundle.getMessage(AbstractVariable.class,
0703:                                    "LBL_BaseClass"); // NOI18N
0704:                            t = info.substring(1, pos - 2).trim();
0705:                            v = info.substring(pos + 1).trim();
0706:                            if (n.startsWith("_vptr")) { // NOI18N
0707:                                return null;
0708:                            }
0709:                        } else {
0710:                            n = info.substring(0, pos - 1).trim();
0711:                            v = info.substring(pos + 1).trim();
0712:                            if (n.startsWith("_vptr")) { // NOI18N
0713:                                return null;
0714:                            }
0715:                            Object o = map.get(n);
0716:                            if (o instanceof  String) {
0717:                                t = o.toString();
0718:                            } else if (o instanceof  Map) {
0719:                                t = (String) ((Map) o).get("<typename>"); // NOI18N
0720:                            } else if (isNumber(v)) {
0721:                                t = "int"; // NOI18N - best guess (std::string drops an "int")
0722:                            } else {
0723:                                log.warning("Cannot determine field type for "
0724:                                        + n); // NOI18N
0725:                                return null;
0726:                            }
0727:                        }
0728:                        return new AbstractField(parent, n, t, v);
0729:                    } else if (info.trim().equals("<No data fields>")) { // NOI18N
0730:                        return new AbstractField(parent, "", "", info.trim()); // NOI18N
0731:                    }
0732:                }
0733:                return null;
0734:            }
0735:
0736:            private void parseCharArray(AbstractVariable var, String basename,
0737:                    String type, String value) {
0738:                String frag;
0739:                int idx = 0;
0740:                int pos;
0741:                boolean truncated = false;
0742:
0743:                while (idx < value.length()) {
0744:                    if (value.substring(idx).startsWith("\\\"")) { // NOI18N
0745:                        pos = value.indexOf("\\\",", idx); // NOI18N
0746:                        if (pos >= 0) {
0747:                            frag = value.substring(idx + 2, pos);
0748:                            idx += frag.length() + 4;
0749:                        } else {
0750:                            // Reached the end of the string...
0751:                            if (value.endsWith("\\\"...")) { // NOI18N
0752:                                frag = value.substring(idx + 2,
0753:                                        value.length() - 5);
0754:                                truncated = true;
0755:                            } else {
0756:                                frag = value.substring(idx + 2,
0757:                                        value.length() - 2);
0758:                            }
0759:                            idx = value.length(); // stop iterating...
0760:                        }
0761:                        parseCharArrayFragment(var, basename, type, frag);
0762:                        if (truncated) {
0763:                            String high;
0764:                            try {
0765:                                high = type.substring(type.indexOf("[") + 1,
0766:                                        type.indexOf("]")); // NOI18N
0767:                                Integer.parseInt(high);
0768:                            } catch (Exception ex) {
0769:                                high = "..."; // NOI18N
0770:                            }
0771:
0772:                            var.addField(new AbstractField(var, basename + "["
0773:                                    + var.fields.length + "-" + high + "]", // NOI18N
0774:                                    "", "...")); // NOI18N
0775:                        }
0776:                    } else if (value.charAt(idx) == ' '
0777:                            || value.charAt(idx) == ',') {
0778:                        idx++;
0779:                    } else {
0780:                        pos = GdbUtils.findNextComma(value, idx);
0781:                        if (pos > 0) {
0782:                            frag = value.substring(idx, pos);
0783:                        } else {
0784:                            frag = value.substring(idx);
0785:                        }
0786:                        parseRepeatArrayFragment(var, basename, type, frag);
0787:                        idx += frag.length();
0788:                    }
0789:                }
0790:            }
0791:
0792:            private void parseRepeatArrayFragment(AbstractVariable var,
0793:                    String basename, String type, String value) {
0794:                String t = type.substring(0, type.indexOf('[')).trim();
0795:                int count;
0796:                int idx = var.fields.length;
0797:                int pos = value.indexOf(' ');
0798:                String val = value.substring(0, pos).replace("\\\\", "\\"); // NOI18N
0799:                int pos1 = value.indexOf("<repeats "); // NOI18N
0800:                int pos2 = value.indexOf(" times>"); // NOI18N
0801:
0802:                try {
0803:                    count = Integer.parseInt(value.substring(pos1 + 9, pos2));
0804:                } catch (Exception ex) {
0805:                    return;
0806:                }
0807:
0808:                while (--count >= 0) {
0809:                    var.addField(new AbstractField(var, basename + "[" + idx++
0810:                            + "]", t, val)); // NOI18N
0811:                }
0812:            }
0813:
0814:            private void parseCharArrayFragment(AbstractVariable var,
0815:                    String basename, String type, String value) {
0816:                String t = type.substring(0, type.indexOf('[')).trim();
0817:                int idx = 0;
0818:                value = value.replace("\\\\", "\\"); // NOI18N - gdb doubles all backslashes...
0819:                int count = value.length();
0820:                int fcount = var.fields.length;
0821:
0822:                while (idx < count) {
0823:                    int vstart = idx;
0824:                    char ch = value.charAt(idx++);
0825:                    String val;
0826:
0827:                    if (ch == '\\' && idx < count) {
0828:                        ch = value.charAt(idx++);
0829:                        if (ch >= '0' && ch <= '7') { // Octal constant
0830:                            StringBuilder sb = new StringBuilder();
0831:                            sb.append('\\');
0832:                            sb.append(ch);
0833:                            int i;
0834:                            for (i = 0; i < 2 && idx < count; i++) {
0835:                                ch = value.charAt(idx);
0836:                                if (ch < '0' || ch > '7') {
0837:                                    break;
0838:                                } else {
0839:                                    sb.append(ch);
0840:                                    idx++;
0841:                                }
0842:                            }
0843:                            val = sb.toString();
0844:                        } else if (ch == 'x' || ch == 'X') { // Hex constant
0845:                            StringBuilder sb = new StringBuilder();
0846:                            sb.append('\\');
0847:                            sb.append(ch);
0848:                            int i;
0849:                            for (i = 0; i < 2 && idx < count; i++) {
0850:                                ch = value.charAt(idx);
0851:                                if ((ch >= '0' && ch <= '9')
0852:                                        || (ch >= 'a' && ch <= 'f')
0853:                                        || (ch >= 'A' && ch <= 'F')) {
0854:                                    break;
0855:                                } else {
0856:                                    sb.append(ch);
0857:                                    idx++;
0858:                                }
0859:                            }
0860:                            val = sb.toString();
0861:                        } else if (value.substring(idx - 1, idx).matches(
0862:                                "['\"?abfnrt]")
0863:                                || ch == '\\') { // NOI18N
0864:                            val = '\\' + value.substring(idx - 1, idx);
0865:                        } else {
0866:                            log
0867:                                    .warning("AV.parseCharArrayFragment: Ignoring invalid character array fragment"); // NOI18N
0868:                            continue;
0869:                        }
0870:                    } else {
0871:                        val = value.substring(vstart, idx);
0872:                    }
0873:                    var.addField(new AbstractField(var, basename + "["
0874:                            + fcount++ + "]", // NOI18N
0875:                            t, '\'' + val + '\''));
0876:                }
0877:            }
0878:
0879:            private void createChildrenForArray(String type, String value) {
0880:                String t;
0881:                int lbpos;
0882:                int cbrace = type.lastIndexOf('}');
0883:                if (cbrace == -1) {
0884:                    lbpos = type.indexOf('[');
0885:                } else {
0886:                    lbpos = type.indexOf('[', cbrace);
0887:                    cbrace = type.indexOf('{');
0888:                }
0889:                int rbpos = GdbUtils.findMatchingBrace(type, lbpos);
0890:                assert rbpos != -1;
0891:                int vstart = 0;
0892:                int vend;
0893:                int size;
0894:                int nextbrace = type.indexOf('[', rbpos);
0895:                String extra;
0896:
0897:                if (nextbrace == -1) {
0898:                    extra = "";
0899:                } else {
0900:                    extra = type.substring(nextbrace);
0901:                }
0902:                if (cbrace == -1) {
0903:                    t = type.substring(0, lbpos).trim() + extra;
0904:                } else {
0905:                    t = type.substring(0, cbrace).trim() + extra;
0906:                }
0907:
0908:                try {
0909:                    size = Integer.valueOf(type.substring(lbpos + 1, rbpos));
0910:                } catch (Exception ex) {
0911:                    size = 0;
0912:                }
0913:                if (t.equals("char")) { // NOI18N
0914:                    parseCharArray(this , getName(), type, value);
0915:                } else {
0916:                    value = value.substring(1, value.length() - 1);
0917:                    for (int i = 0; i < size && vstart != -1; i++) {
0918:                        if (value.charAt(vstart) == '{') {
0919:                            vend = GdbUtils.findNextComma(value, GdbUtils
0920:                                    .findMatchingCurly(value, vstart));
0921:                        } else {
0922:                            vend = GdbUtils.findNextComma(value, vstart);
0923:                        }
0924:                        addField(new AbstractField(this , getName() + "[" + i
0925:                                + "]", t, // NOI18N
0926:                                vend == -1 ? value.substring(vstart) : value
0927:                                        .substring(vstart, vend)));
0928:                        vstart = GdbUtils.firstNonWhite(value, vend + 1);
0929:                    }
0930:                }
0931:            }
0932:
0933:            /**
0934:             * Adds a field.
0935:             *
0936:             * Note: completeFieldDefinition returns null for _vptr data. Its easier to let it return null and
0937:             * ignore it here than to check the return value in expandChildrenFromValue and not call addField
0938:             * if its null.
0939:             *
0940:             * @parameter field A field to add.
0941:             */
0942:            public void addField(Field field) {
0943:                if (field != null) {
0944:                    int n = fields.length;
0945:                    Field[] fv = new Field[n + 1];
0946:                    System.arraycopy(fields, 0, fv, 0, n);
0947:                    fields = fv;
0948:                    fields[n] = field;
0949:                }
0950:            }
0951:
0952:            public void addPropertyChangeListener(PropertyChangeListener l) {
0953:                listeners.add(l);
0954:            }
0955:
0956:            public void removePropertyChangeListener(PropertyChangeListener l) {
0957:                listeners.remove(l);
0958:            }
0959:
0960:            @Override
0961:            public String toString() {
0962:                return getFullName(false);
0963:            }
0964:
0965:            private boolean isNumber(String value) {
0966:                try {
0967:                    Long.parseLong(value);
0968:                    return true;
0969:                } catch (NumberFormatException ex) {
0970:                    return false;
0971:                }
0972:            }
0973:
0974:            public String getFullName() {
0975:                return getFullName(false);
0976:            }
0977:
0978:            public String getFullName(boolean showBase) {
0979:                if (this  instanceof  AbstractField) {
0980:                    return ((AbstractField) this ).getFullName(showBase);
0981:                } else {
0982:                    return getName();
0983:                }
0984:            }
0985:
0986:            public class AbstractField extends AbstractVariable implements 
0987:                    Field {
0988:
0989:                private AbstractVariable parent;
0990:
0991:                public AbstractField(AbstractVariable parent, String name,
0992:                        String type, String value) {
0993:                    if (name.startsWith("static ")) { // NOI18N
0994:                        this .name = name.substring(7);
0995:                    } else {
0996:                        this .name = name;
0997:                    }
0998:                    int lcurly = type.indexOf('{');
0999:                    if (lcurly == -1) {
1000:                        this .type = type;
1001:                    } else {
1002:                        int rcurly = type.indexOf('}', lcurly);
1003:                        this .type = type.substring(0, lcurly).trim()
1004:                                + type.substring(rcurly + 1);
1005:                    }
1006:                    this .parent = parent;
1007:                    fields = new Field[0];
1008:                    derefValue = null;
1009:                    tinfo = null;
1010:
1011:                    if (Utilities.getOperatingSystem() == Utilities.OS_MAC) {
1012:                        this .value = GdbUtils.mackHack(value);
1013:                    } else {
1014:                        this .value = value;
1015:                    }
1016:                }
1017:
1018:                public boolean isStatic() {
1019:                    return false;
1020:                }
1021:
1022:                @Override
1023:                public String getFullName(boolean showBaseClass) {
1024:                    String pname; // parent part of name
1025:                    String fullname;
1026:                    int pos;
1027:
1028:                    if (parent instanceof  AbstractField) {
1029:                        pname = ((AbstractField) parent)
1030:                                .getFullName(showBaseClass);
1031:                    } else {
1032:                        pname = parent.getName();
1033:                    }
1034:
1035:                    if (name.equals(NbBundle.getMessage(AbstractVariable.class,
1036:                            "LBL_BaseClass"))) { // NOI18N
1037:                        if (showBaseClass) {
1038:                            fullname = pname + ".<" + type + ">"; // NOI18N
1039:                        } else {
1040:                            fullname = pname;
1041:                        }
1042:                    } else if (name.indexOf('[') != -1) {
1043:                        if ((pos = pname.lastIndexOf('.')) != -1) {
1044:                            fullname = pname.substring(0, pos) + '.' + name;
1045:                        } else {
1046:                            fullname = name;
1047:                        }
1048:                    } else if (GdbUtils.isSimplePointer(parent.getType())
1049:                            && name.startsWith("*")) { // NOI18N
1050:                        fullname = '*' + pname;
1051:                    } else if (GdbUtils.isPointer(parent.getType())) {
1052:                        fullname = pname + "->" + name; // NOI18N
1053:                    } else if (name.length() > 0) {
1054:                        fullname = pname + '.' + name;
1055:                    } else {
1056:                        fullname = pname;
1057:                    }
1058:                    return fullname;
1059:                }
1060:            }
1061:        }
w__ww_.__j__a__va2_s_.__c_o_m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.