001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package dwarfvsmodel;
043:
044: import java.util.Comparator;
045: import java.util.Iterator;
046: import org.netbeans.modules.cnd.api.model.*;
047: import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
048: import org.netbeans.modules.cnd.dwarfdump.dwarf.DwarfEntry;
049: import org.netbeans.modules.cnd.dwarfdump.dwarfconsts.ATTR;
050: import org.netbeans.modules.cnd.dwarfdump.dwarfconsts.TAG;
051:
052: /**
053: * Common functions needed for comparison
054: * (and probably not only just for comparison)
055: * @author Vladimir Kvashin
056: */
057: public class ComparisonUtils {
058:
059: public static class DwarfEntryComparator implements
060: Comparator<DwarfEntry> {
061: public int compare(DwarfEntry entry1, DwarfEntry entry2) {
062: int line1 = entry1.getLine();
063: int line2 = entry2.getLine();
064: return line1 - line2;
065: }
066:
067: public boolean equals(Object obj) {
068: return this == obj;
069: }
070: }
071:
072: public static class CsmDeclarationComparator implements
073: Comparator<CsmDeclaration> {
074: public int compare(CsmDeclaration decl1, CsmDeclaration decl2) {
075: int line1 = ((CsmOffsetable) decl1).getStartOffset();
076: int line2 = ((CsmOffsetable) decl2).getStartOffset();
077: return line1 - line2;
078: }
079:
080: public boolean equals(Object obj) {
081: return this == obj;
082: }
083: }
084:
085: public static String getText(CsmType type) {
086: CsmClassifier classifier = type.getClassifier();
087: String text = CsmTypeGetText(type, classifier); //type.getText();
088: if ((classifier == null || classifier.getClass().getName()
089: .endsWith("UnresolvedClass"))
090: && !DMFlags.UNRESOLVED_TOLERANT) { // NOI18N
091: text = "unresolved::" + text; // NOI18N
092: }
093: // We don't need this workaround since this is solved on Dwarf side
094: // else {
095: // // Workaround: dwarf duplicates "const" in the case of const references
096: // // so we're adding one more "const" too here
097: // if( type.isReference() && type.isConst() ) {
098: // text = "const " + text; // NOI18N
099: // }
100: // }
101: return text;
102: }
103:
104: /**
105: * Almost exact copy of CsmType.getText
106: *
107: * It's rather strange to have it as a separate function, but in this case
108: * it's easier to understand it's the same as CsmType.getText.
109: *
110: * Why do we need this copy? To use classifier instead of getting text as it's written in code.
111: * CsmType doesn't use getClassifier() because it's too expensive
112: */
113: private static String CsmTypeGetText(CsmType type,
114: CsmClassifier classifier) {
115: if (DMFlags.UNRESOLVED_TOLERANT && classifier == null) {
116: return type.getText();
117: }
118: // if( text == null ) {
119: StringBuffer sb = new StringBuffer();
120: if (type.isConst()) {
121: sb.append("const "); // NOI18N
122: }
123: sb.append(classifier == null ? "unresolved" : classifier
124: .getName()); // NOI18N
125: for (int i = 0; i < type.getPointerDepth(); i++) {
126: sb.append('*');
127: }
128: if (type.isReference()) {
129: sb.append('&');
130: }
131: for (int i = 0; i < type.getArrayDepth(); i++) {
132: sb.append("[]"); // NOI18N
133: }
134: // text = sb.toString();
135: // }
136: // return text;
137: return sb.toString();
138: }
139:
140: /**
141: * Gets function signature
142: * copy-pasted from FunctionImpl.getSignature,
143: * then modified to show unresolved
144: */
145: public static String getSignature(CsmFunction function) {
146: // TODO: this fake implementation for Deimos only!
147: // we should resolve parameter types and provide
148: // kind of canonical representation here
149: StringBuffer sb = new StringBuffer(function.getName());
150: sb.append('(');
151: for (Iterator iter = function.getParameters().iterator(); iter
152: .hasNext();) {
153: CsmParameter param = (CsmParameter) iter.next();
154: CsmType type = param.getType();
155: if (type != null) {
156: sb.append(getText(type)); // type.getText()
157: if (iter.hasNext()) {
158: sb.append(',');
159: }
160: }
161: }
162: sb.append(')');
163: if (isConst(function)) {
164: sb.append(" const"); // NOI18N
165: }
166: return sb.toString();
167: }
168:
169: private static boolean isConst(CsmFunction function) {
170: CsmMethod method = null;
171: if (CsmKindUtilities.isMethodDeclaration(function)) {
172: method = (CsmMethod) function;
173: } else if (CsmKindUtilities.isFunctionDefinition(function)) {
174: CsmFunction decl = ((CsmFunctionDefinition) function)
175: .getDeclaration();
176: if (CsmKindUtilities.isMethod(decl)) {
177: method = (CsmMethod) decl;
178: }
179: }
180: return (method == null) ? false : method.isConst();
181: }
182:
183: public static boolean isArtificial(DwarfEntry entry) {
184: if (entry.getAttributeValue(ATTR.DW_AT_abstract_origin) != null) {
185: return true;
186: }
187: if (entry.getAttributeValue(ATTR.DW_AT_artificial) != null) {
188: return true;
189: }
190: String qname = entry.getQualifiedName();
191: if (qname != null && qname.startsWith("_GLOBAL__")) { // NOI18N
192: return true;
193: } else {
194: return false;
195: }
196: }
197:
198: public static boolean isEmpty(String s) {
199: return s == null || s.length() == 0;
200: }
201:
202: public static String getQualifiedName(CsmDeclaration decl) {
203: if (CsmKindUtilities.isVariableDefinition(decl)) {
204: CsmVariable var = ((CsmVariableDefinition) decl)
205: .getDeclaration();
206: if (var != null) {
207: return var.getQualifiedName();
208: }
209: }
210: return decl.getQualifiedName();
211: }
212:
213: public static boolean isFunction(DwarfEntry entry) {
214: TAG kind = entry.getKind();
215: switch (kind) {
216: case DW_TAG_member:
217: case DW_TAG_subroutine_type:
218: case DW_TAG_subprogram:
219: return true;
220: default:
221: return false;
222: }
223: }
224:
225: public static boolean isEnum(DwarfEntry entry) {
226: TAG kind = entry.getKind();
227: switch (kind) {
228: case DW_TAG_enumeration_type:
229: return true;
230: default:
231: return false;
232: }
233: }
234:
235: public static boolean isVariable(DwarfEntry entry) {
236: TAG kind = entry.getKind();
237: switch (kind) {
238: case DW_TAG_variable:
239: case DW_TAG_member:
240: case DW_TAG_formal_parameter:
241: case DW_TAG_unspecified_parameters:
242: case DW_TAG_constant:
243: return true;
244: default:
245: return false;
246: }
247: }
248:
249: public static boolean isClass(DwarfEntry entry) {
250: TAG kind = entry.getKind();
251: switch (kind) {
252: case DW_TAG_SUN_class_template:
253: case DW_TAG_interface_type:
254: case DW_TAG_structure_type:
255: //case DW_TAG_typedef:
256: case DW_TAG_union_type:
257: return true;
258: default:
259: return false;
260: }
261: }
262:
263: public static boolean isTypedef(DwarfEntry entry) {
264: TAG kind = entry.getKind();
265: switch (kind) {
266: case DW_TAG_typedef:
267: return true;
268: default:
269: return false;
270: }
271: }
272:
273: public static boolean isParameter(DwarfEntry entry) {
274: TAG kind = entry.getKind();
275: switch (kind) {
276: case DW_TAG_formal_parameter:
277: case DW_TAG_unspecified_parameters:
278: return true;
279: default:
280: return false;
281: }
282: }
283:
284: public static String getName(DwarfEntry entry) {
285: String name = entry.getName();
286: if (name.indexOf('<') >= 0) {
287: StringBuilder sb = new StringBuilder();
288: int level = 0;
289: for (int i = 0; i < name.length(); i++) {
290: char c = name.charAt(i);
291: if (c == '<') {
292: level++;
293: } else if (c == '<') {
294: level--;
295: } else if (level == 0) {
296: sb.append(c);
297: }
298: }
299: name = sb.toString();
300: }
301: name = name.replaceAll(" ", ""); // NOI18N
302: return name;
303: }
304: }
|