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 }