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.io.PrintStream;
045: import java.util.*;
046: import org.netbeans.modules.cnd.dwarfdump.dwarf.DwarfEntry;
047: import org.netbeans.modules.cnd.dwarfdump.CompilationUnit;
048: import org.netbeans.modules.cnd.dwarfdump.dwarfconsts.ATTR;
049: import org.netbeans.modules.cnd.dwarfdump.dwarfconsts.TAG;
050:
051: /**
052: * A list of high-level dwarf declarations - variables and functions
053: * @author vk155633
054: */
055: public class DwarfList {
056:
057: private CompilationUnit compilationUnit;
058: private List<DwarfEntry> entries = new ArrayList<DwarfEntry>();
059: private Map<DwarfEntry, String> entry2fqn = new HashMap<DwarfEntry, String>();
060: private Map<String, List<DwarfEntry>> fqn2entry = new HashMap<String, List<DwarfEntry>>();
061:
062: /** Creates a new instance of DwarfList */
063: public DwarfList(CompilationUnit compilationUnit) {
064: this .compilationUnit = compilationUnit;
065: add(compilationUnit.getDeclarations());
066: }
067:
068: public DwarfList(CompilationUnit compilationUnit, DwarfEntry entry) {
069: this .compilationUnit = compilationUnit;
070: add(entry.getChildren());
071: }
072:
073: private static enum Rule {
074: Ignore, Add, AddChildren
075: }
076:
077: private void add(Iterable<DwarfEntry> currEntries) {
078: for (DwarfEntry entry : currEntries) {
079: Rule rule = getRule(entry);
080: switch (rule) {
081: case Add:
082: add(entry);
083: break;
084: case AddChildren:
085: add(entry.getChildren());
086: break;
087: case Ignore:
088: default:
089: //nothing
090: }
091: }
092: }
093:
094: private void add(DwarfEntry entry) {
095:
096: String fqn = getQualifiedName(entry);
097:
098: List<DwarfEntry> overloads = fqn2entry.get(fqn);
099: if (overloads == null) {
100: overloads = new ArrayList<DwarfEntry>();
101: fqn2entry.put(fqn, overloads);
102: }
103:
104: // for templates, dwarf places an instance for each template instantiation
105: // skip them
106: for (DwarfEntry overload : overloads) {
107: if (overload.getLine() == entry.getLine()) {
108: //System.err.println("\Excluding \n\t" + entry + " \n\tbecause found \n\t" + overload + "\n");
109: return;
110: }
111: }
112:
113: if (overloads.size() > 0) {
114: // specification and definition shouldn't be both in a list
115: DwarfEntry spec = entry.getSpecification();
116: if (spec != null) {
117: // this is a definition
118: if (spec != entry
119: && Collections.replaceAll(overloads, spec,
120: entry)) {
121: Collections.replaceAll(entries, spec, entry);
122: } else {
123: overloads.add(entry);
124: entries.add(entry);
125: }
126: } else {
127: // spec == null, let's find a definition
128: DwarfEntry def = entry.getDefinition();
129: if (!overloads.contains(def)) {
130: overloads.add(entry);
131: entries.add(entry);
132: }
133: }
134: } else {
135: overloads.add(entry);
136: entries.add(entry);
137: }
138: }
139:
140: public Iterable<DwarfEntry> getDeclarations(String qualifiedName) {
141: List<DwarfEntry> entries = fqn2entry.get(qualifiedName);
142: return entries == null ? (Iterable<DwarfEntry>) Collections.EMPTY_LIST
143: : entries;
144: }
145:
146: private Rule getRule(DwarfEntry entry) {
147: if (ComparisonUtils.isArtificial(entry)) {
148: return Rule.Ignore;
149: }
150: TAG kind = entry.getKind();
151: switch (kind) {
152: case DW_TAG_array_type:
153: case DW_TAG_class_type:
154: case DW_TAG_structure_type:
155: case DW_TAG_enumeration_type:
156: case DW_TAG_member:
157: case DW_TAG_string_type:
158: case DW_TAG_subroutine_type:
159: case DW_TAG_union_type:
160: case DW_TAG_interface_type:
161: case DW_TAG_namespace:
162: case DW_TAG_SUN_class_template:
163: return Rule.AddChildren;
164: case DW_TAG_variable:
165: case DW_TAG_typedef:
166: case DW_TAG_constant:
167: case DW_TAG_enumerator:
168: case DW_TAG_subprogram:
169: return Rule.Add;
170: case DW_TAG_inheritance:
171: case DW_TAG_access_declaration:
172: // description seems very interesting, but I never seen such entries in dump :(
173: return Rule.Ignore;
174: // TODO: divide the below list into 2 parts:
175: // 1) just to ignore
176: // 2) to report warning (entries that should never occur here)
177: case DW_TAG_inlined_subroutine:
178: case DW_TAG_lexical_block:
179: case DW_TAG_try_block:
180: case DW_TAG_imported_declaration:
181: case DW_TAG_label:
182: case DW_TAG_entry_point:
183: case DW_TAG_common_block:
184: case DW_TAG_common_inclusion:
185: case DW_TAG_pointer_type:
186: case DW_TAG_reference_type:
187: case DW_TAG_compile_unit:
188: case DW_TAG_unspecified_parameters:
189: case DW_TAG_variant:
190: case DW_TAG_module:
191: case DW_TAG_ptr_to_member_type:
192: case DW_TAG_set_type:
193: case DW_TAG_subrange_type:
194: case DW_TAG_with_stmt:
195: case DW_TAG_base_type:
196: case DW_TAG_catch_block:
197: case DW_TAG_const_type:
198: case DW_TAG_file_type:
199: case DW_TAG_friend:
200: case DW_TAG_namelist:
201: case DW_TAG_namelist_item:
202: case DW_TAG_packed_type:
203: case DW_TAG_template_type_param:
204: case DW_TAG_template_value_param:
205: case DW_TAG_thrown_type:
206: case DW_TAG_variant_part:
207: case DW_TAG_volatile_type:
208: case DW_TAG_dwarf_procedure:
209: case DW_TAG_restrict_type:
210: case DW_TAG_imported_module:
211: case DW_TAG_unspecified_type:
212: case DW_TAG_partial_unit:
213: case DW_TAG_imported_unit:
214: case DW_TAG_condition:
215: case DW_TAG_shared_type:
216: case DW_TAG_lo_user:
217: case DW_TAG_SUN_rtti_descriptor:
218: case DW_TAG_hi_user:
219: case DW_TAG_formal_parameter:
220: return Rule.Ignore;
221: default:
222: System.err.println("!!! unknown node kind: " + kind);
223: return Rule.Ignore;
224: }
225: }
226:
227: public Iterable<DwarfEntry> getDeclarations() {
228: return entries;
229: }
230:
231: public String getQualifiedName(DwarfEntry entry) {
232: String fqn = entry2fqn.get(entry);
233: if (fqn == null) {
234: fqn = findQualifiedName(entry);
235: entry2fqn.put(entry, fqn);
236: }
237: return fqn;
238: }
239:
240: private String findQualifiedName(DwarfEntry entry) {
241: if (entry == null) {
242: return "";
243: }
244: String fqn = null; // unfortunately we can't rely on entry.getQualifiedName();
245: if (ComparisonUtils.isEmpty(fqn)) {
246: DwarfEntry spec = entry.getSpecification();
247: if (spec != null) {
248: return getQualifiedName(spec);
249: } else {
250: DwarfEntry parent = entry.getParent();
251: String parentQName = getQualifiedName(parent);
252: if (ComparisonUtils.isEmpty(parentQName)) {
253: Rule rule = getRule(entry);
254: switch (rule) {
255: case Add:
256: case AddChildren:
257: return ComparisonUtils.getName(entry);
258: case Ignore:
259: default:
260: return "";
261: }
262: } else {
263: return parentQName + "::"
264: + ComparisonUtils.getName(entry); // NOI18N
265: }
266: }
267: } else {
268: return fqn;
269: }
270: }
271:
272: public String qualifiedNameFromMangled(DwarfEntry entry) {
273: String ln = (String) entry
274: .getAttributeValue(ATTR.DW_AT_MIPS_linkage_name);
275: if (ln != null) {
276: if (ln.startsWith("_ZN")) { // NOI18N
277: int pos = 3;
278: StringBuilder qn = new StringBuilder();
279: if (ln.startsWith("_ZNSt")) { // NOI18N
280: pos += 2;
281: qn.append("std::"); // NOI18N
282: }
283: while (pos < ln.length()
284: && Character.isDigit(ln.charAt(pos))) {
285: int len = 0;
286: int mul = 1;
287: for (char c = ln.charAt(pos); pos < ln.length()
288: && Character.isDigit(c); c = ln
289: .charAt(++pos)) {
290: len *= 10;
291: len += (int) c - (int) '0';
292: }
293: if (len <= 0) {
294: return null;
295: }
296: if (pos + len > ln.length()) {
297: return null;
298: }
299: if (qn.length() > 0) {
300: qn.append("::"); // NOI18N
301: }
302: qn.append(ln.substring(pos, pos + len));
303: pos += len;
304: }
305: if (qn.length() > 0) {
306: String name = entry.getName();
307: if (name.startsWith("operator")
308: && !Character.isJavaIdentifierPart(name
309: .charAt(8))) { // NOI18N
310: qn.append("::"); // NOI18N
311: qn.append(name);
312: }
313: return qn.toString();
314: }
315: }
316: }
317: return null;
318: }
319:
320: public void dump(PrintStream ps, boolean bodies) {
321: ps.println("==== Dwarf comparison list for "
322: + compilationUnit.getSourceFileName() + " "
323: + compilationUnit.getSourceFileFullName()); // NOI18N
324: List<DwarfEntry> sorted = new ArrayList<DwarfEntry>(entries);
325: Collections.sort(sorted,
326: new ComparisonUtils.DwarfEntryComparator());
327: for (DwarfEntry entry : sorted) {
328: dump(ps, entry, bodies);
329: }
330: ps.println("\n"); // NOI18N
331: }
332:
333: private void dump(PrintStream ps, DwarfEntry entry, boolean bodies) {
334: ps.println(toString(entry));
335: if (bodies && ComparisonUtils.isFunction(entry)) {
336: Node<DwarfEntry> node = DwarfTree.createDwarfNode(entry);
337: Tracer tr = new Tracer(ps);
338: tr.indent();
339: tr.traceDwarf(node);
340: }
341: }
342:
343: public String toString(DwarfEntry entry) {
344: return getQualifiedName(entry) + " "
345: + entry.getDeclaration(); // NOI18N
346: }
347: }
|