blob: 7982900f9bf0eadeaddbcf1a8c122af94c6d4896 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2006,2007 IBM Corporation.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ptp.pldt.openmp.analysis.dictionary;
import java.util.Hashtable;
import java.util.LinkedList;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
/**
* Dictionary for entire file - global scope and function scopes
* <br>
* The dictionary is mainly used to query for symbols within certain scopes
* and each symbol tells where it is defined, see getSymbolsFor().<br>
* Would be good to develop further with "where used" information
*
* @author pazel
*/
public class Dictionary
{
// maps string to linked list of symbols having the same name
protected Hashtable textToSymbols_ = new Hashtable();
// maps function (or ast for globals) to linked list of all symbols defined in that function
protected Hashtable functionToSymbols_ = new Hashtable();
protected Hashtable stringScopeKeyToSymbol_ = new Hashtable();
protected IASTTranslationUnit ast_ = null;
/**
* Dictionary - File dictionary
* @param ast - IASTTranslationUnit
*/
public Dictionary(IASTTranslationUnit ast)
{
ast_ = ast;
functionToSymbols_.put(ast_, new LinkedList());
}
/**
* insert - insert a set of symbol specifications using a simple declartion
* @param decl - IASTSimpleDeclaration
*/
public void insert(IASTSimpleDeclaration decl)
{
IASTDeclarator [] decls = decl.getDeclarators();
for(int i=0; i<decls.length; i++)
insert(decls[i], decl);
}
/**
* insert - insert a declarator into the dictionaries
* @param declarator - IASTDeclarator
* @param decl - IASTDeclaration
*/
public void insert(IASTDeclarator declarator, IASTDeclaration decl){
Symbol symbol = new Symbol(declarator, decl);
insertMember(symbol);
}
/**
* insert - insert a declarator into the dictionaries
* @param declarator - IASTDeclarator
* @param decl - IASTDeclaration
*/
public void insert(IASTDeclarator declarator, IASTParameterDeclaration decl){
Symbol symbol = new Symbol(declarator, decl);
insertMember(symbol);
}
protected void insertMember(Symbol symbol)
{
IASTNode node = symbol.getDefiningFunction();
// add to string/scope
try {
StringScopeKey sskey = new StringScopeKey(symbol.getName());
stringScopeKeyToSymbol_.put(sskey, symbol);
}
catch(DOMException e) {
System.out.println("Dictionary.insert exception "+e);
}
// Add to function global lists
if (node==null) node = ast_; // ?? maybe should exit instead??
LinkedList ll = (LinkedList)functionToSymbols_.get(node);
if (ll==null) {
ll = new LinkedList();
functionToSymbols_.put(node, ll);
}
ll.add(symbol);
// Add to text list
String strname = symbol.getName().toString();
LinkedList nl = (LinkedList)textToSymbols_.get(strname);
if (nl==null) {
nl = new LinkedList(); // definitions for this text name
textToSymbols_.put(strname, nl);
}
nl.add(symbol);
}
/**
* getSymbolsFor - for a name string, using the global dicationary
* @param text - String
* @return Symbol []
*/
public Symbol [] getSymbolsFor(String text)
{
LinkedList ll = (LinkedList)textToSymbols_.get(text);
if (ll==null) return new Symbol[0];
Symbol [] ans = new Symbol[ll.size()];
for(int i=0; i<ll.size(); i++) ans[i] = (Symbol)ll.get(i);
return ans;
}
/**
* getSymbolsFor - using a given function scope
* @param fctnDef - IASTFunctionDefinition
* @return Symbol []
*/
public Symbol [] getSymbolsFor(IASTFunctionDefinition fctnDef)
{
LinkedList ll = (LinkedList)functionToSymbols_.get(fctnDef);
if (ll==null) return new Symbol[0];
Symbol [] ans = new Symbol[ll.size()];
for(int i=0; i<ll.size(); i++) ans[i] = (Symbol)ll.get(i);
return ans;
}
/**
* getSymbolsFor - using the global scope
* @return Symbol []
*/
public Symbol [] getSymbolsFor()
{
LinkedList ll = (LinkedList)functionToSymbols_.get(ast_);
if (ll==null) return new Symbol[0];
Symbol [] ans = new Symbol[ll.size()];
for(int i=0; i<ll.size(); i++) ans[i] = (Symbol)ll.get(i);
return ans;
}
/**
* find - given an IASTName (references, for example)
* @param name - IASTName
* @return Symbol
* @throws DOMException
*/
public Symbol find(IASTName name) throws DOMException
{
StringScopeKey key = new StringScopeKey(name);
return (Symbol)stringScopeKeyToSymbol_.get(key);
}
//-------------------------------------------------------------------------
// Class: StringScopeKey - binding identity of name and scope where defined
//-------------------------------------------------------------------------
protected static class StringScopeKey
{
public String stringKey_ = "";
public IScope scopeKey_ = null;
public StringScopeKey(String stringKey, IScope scopeKey)
{
stringKey_ = stringKey;
scopeKey_ = scopeKey;
}
public StringScopeKey(IASTName nameNode) throws DOMException
{
stringKey_ = nameNode.toString();
//IBinding b = nameNode.resolveBinding();
//if (b instanceof IVariable) {
// IVariable biv = (IVariable)b;
// IType t = biv.getType();
// t=null;
//}
IBinding binding=nameNode.resolveBinding();//cdt40 fix: was getBinding(); could have been null
scopeKey_ = binding.getScope();
}
/**
* equals
* NOTE - This is what makes the stringScopeKeyToSymbol_ hashtable work.
* allowing two StringScopeKeys with identical data fields to be "identified"
* by the hashtable.
*/
public boolean equals(Object that)
{
if ( this == that ) return true;
if ( !(that instanceof StringScopeKey) ) return false;
StringScopeKey thatStringScopeKey = (StringScopeKey)that;
if (thatStringScopeKey.stringKey_.equals(stringKey_) && thatStringScopeKey.scopeKey_==scopeKey_) return true;
return false;
}
/**
* equals
* NOTE - This is what makes the stringScopeKeyToSymbol_ hashtable work
*/
public int hashCode() {
return stringKey_.hashCode();
}
}
}