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