1 package net.sourceforge.pmd.cpd.cppast; 2 3 import java.util.Hashtable; 4 5 /*** 6 * Manages the symbol table and scopes within a given compilation unit. 7 */ 8 public class SymtabManager { 9 /*** 10 * Global symbol table indexed by the name of the scope (class/function). 11 */ 12 static Hashtable scopeTable = new Hashtable(); 13 14 /*** 15 * Stack of scopes. Currently max. nesting allowed is 100. 16 */ 17 static Scope[] scopeStack = new Scope[100]; 18 19 /*** 20 * Current depth of scope nesting. 21 */ 22 static int depth = 0; 23 24 /*** 25 * Dummy at the bottom of the stack so that no need to check for null. 26 */ 27 static { 28 scopeStack[depth] = new Scope(null); 29 } 30 31 /*** 32 * Opens a new scope (with optional name and type flag). 33 */ 34 public static Scope OpenScope(String scopeName, boolean isType) { 35 Scope newScope; 36 37 if (scopeName != null) { 38 if (isType) { 39 newScope = new ClassScope(scopeName, scopeStack[depth]); 40 scopeStack[depth].PutTypeName(scopeName, newScope); 41 } else { 42 newScope = new Scope(scopeName, isType, scopeStack[depth]); 43 } 44 45 scopeTable.put(scopeName, newScope); 46 } else 47 newScope = new Scope(scopeStack[depth]); 48 49 scopeStack[++depth] = newScope; 50 return newScope; 51 } 52 53 public static void OpenScope(Scope sc) { 54 scopeStack[++depth] = sc; 55 } 56 57 public static void PutTypeName(String name) { 58 scopeStack[depth].PutTypeName(name); 59 } 60 61 public static boolean IsFullyScopedTypeName(String name) { 62 if (name == null) 63 return false; 64 65 if (name.indexOf("::") == -1) 66 return IsTypeName(name); 67 68 Scope sc = GetScopeOfFullyScopedName(name); 69 70 if (sc != null) 71 return sc.IsTypeName(name.substring(name.lastIndexOf("::") + 2, 72 name.length())); 73 74 return false; 75 } 76 77 public static boolean IsTypeName(String name) { 78 int i = depth; 79 80 while (i >= 0) { 81 if (scopeStack[i--].IsTypeName(name)) 82 return true; 83 } 84 85 return false; 86 } 87 88 public static void CloseScope() { 89 depth--; 90 } 91 92 /*** 93 * For now, we just say if it is a class name, it is OK to call it a 94 * constructor. 95 */ 96 public static boolean IsCtor(String name) { 97 if (name == null) 98 return false; 99 100 if (name.indexOf("::") == -1) 101 return GetScope(name) != null; 102 103 Scope sc = GetScopeOfFullyScopedName(name); 104 105 if (sc != null && sc.parent != null) 106 return sc.parent.GetScope(name.substring(name.lastIndexOf("::") + 2, 107 name.length())) == sc; 108 109 return false; 110 } 111 112 public static Scope GetCurScope() { 113 return scopeStack[depth]; 114 } 115 116 public static Scope GetScope(String name) { 117 int i = depth; 118 Scope sc = null; 119 120 while (i >= 0) 121 if ((sc = scopeStack[i--].GetScope(name)) != null) 122 return sc; 123 124 return null; 125 } 126 127 /*** 128 * Returns the Scope of B in A::B::C. 129 */ 130 public static Scope GetScopeOfFullyScopedName(String name) { 131 Scope sc; 132 int i = 0, j = 0; 133 134 if (name.indexOf("::") == -1) 135 return GetScope(name); 136 137 if (name.indexOf("::") == 0) { 138 sc = scopeStack[1]; 139 j = 2; 140 } else 141 sc = GetCurScope(); 142 143 String tmp = name.substring(j, name.lastIndexOf("::")); 144 145 while ((j = tmp.indexOf("::", i)) != -1) { 146 sc = sc.GetScope(tmp.substring(i, j)); 147 i = j + 2; 148 149 if (sc == null) 150 return null; 151 } 152 153 if (sc == GetCurScope()) 154 return GetScope(tmp.substring(i, tmp.length())); 155 156 return sc.GetScope(tmp.substring(i, tmp.length())); 157 } 158 159 public static boolean IsGlobalScope() { 160 return depth == 1 || depth == 2; 161 } 162 }