Thu, 24 May 2018 16:41:12 +0800
Merge
1 /*
2 * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 /*
27 * Licensed Materials - Property of IBM
28 * RMI-IIOP v1.0
29 * Copyright IBM Corp. 1998 1999 All Rights Reserved
30 *
31 */
33 package sun.rmi.rmic.iiop;
35 import sun.tools.java.CompilerError;
37 /**
38 * ContextStack provides a mechanism to record parsing state.
39 *
40 * @author Bryan Atsatt
41 */
42 public class ContextStack {
44 // Context codes.
46 public static final int TOP = 1;
48 public static final int METHOD = 2;
49 public static final int METHOD_RETURN = 3;
50 public static final int METHOD_ARGUMENT = 4;
51 public static final int METHOD_EXCEPTION = 5;
53 public static final int MEMBER = 6;
54 public static final int MEMBER_CONSTANT = 7;
55 public static final int MEMBER_STATIC = 8;
56 public static final int MEMBER_TRANSIENT = 9;
58 public static final int IMPLEMENTS = 10;
59 public static final int EXTENDS = 11;
61 // String versions of context codes.
63 private static final String[] CODE_NAMES = {
64 "UNKNOWN ",
65 "Top level type ",
66 "Method ",
67 "Return parameter ",
68 "Parameter ",
69 "Exception ",
70 "Member ",
71 "Constant member ",
72 "Static member ",
73 "Transient member ",
74 "Implements ",
75 "Extends ",
76 };
77 // Member data.
79 private int currentIndex = -1;
80 private int maxIndex = 100;
81 private TypeContext[] stack = new TypeContext[maxIndex];
82 private int newCode = TOP;
83 private BatchEnvironment env = null;
84 private boolean trace = false;
85 private TypeContext tempContext = new TypeContext();
87 private static final String TRACE_INDENT = " ";
89 /**
90 * Constructor.
91 */
92 public ContextStack (BatchEnvironment env) {
93 this.env = env;
94 env.contextStack = this;
95 }
97 /**
98 * Return true if env.nerrors > 0.
99 */
100 public boolean anyErrors () {
101 return env.nerrors > 0;
102 }
104 /**
105 * Enable/disable tracing.
106 */
107 public void setTrace(boolean trace) {
108 this.trace = trace;
109 }
111 /**
112 * Check trace flag.
113 */
114 public boolean isTraceOn() {
115 return trace;
116 }
118 /**
119 * Get the environment.
120 */
121 public BatchEnvironment getEnv() {
122 return env;
123 }
125 /**
126 * Set the new context.
127 */
128 public void setNewContextCode(int code) {
129 newCode = code;
130 }
132 /**
133 * Get the current context code.
134 */
135 public int getCurrentContextCode() {
136 return newCode;
137 }
140 /**
141 * If tracing on, write the current call stack (not the context stack) to
142 * System.out.
143 */
144 final void traceCallStack () {
145 if (trace) dumpCallStack();
146 }
148 public final static void dumpCallStack() {
149 new Error().printStackTrace(System.out);
150 }
152 /**
153 * Print a line indented by stack depth.
154 */
155 final private void tracePrint (String text, boolean line) {
156 int length = text.length() + (currentIndex * TRACE_INDENT.length());
157 StringBuffer buffer = new StringBuffer(length);
158 for (int i = 0; i < currentIndex; i++) {
159 buffer.append(TRACE_INDENT);
160 }
161 buffer.append(text);
162 if (line) {
163 buffer.append("\n");
164 }
165 System.out.print(buffer.toString());
166 }
168 /**
169 * If tracing on, print a line.
170 */
171 final void trace (String text) {
172 if (trace) {
173 tracePrint(text,false);
174 }
175 }
177 /**
178 * If tracing on, print a line followed by a '\n'.
179 */
180 final void traceln (String text) {
181 if (trace) {
182 tracePrint(text,true);
183 }
184 }
186 /**
187 * If tracing on, print a pre-mapped ContextElement.
188 */
189 final void traceExistingType (Type type) {
190 if (trace) {
191 tempContext.set(newCode,type);
192 traceln(toResultString(tempContext,true,true));
193 }
194 }
196 /**
197 * Push a new element on the stack.
198 * @return the new element.
199 */
200 public TypeContext push (ContextElement element) {
202 currentIndex++;
204 // Grow array if need to...
206 if (currentIndex == maxIndex) {
207 int newMax = maxIndex * 2;
208 TypeContext[] newStack = new TypeContext[newMax];
209 System.arraycopy(stack,0,newStack,0,maxIndex);
210 maxIndex = newMax;
211 stack = newStack;
212 }
214 // Make sure we have a context object to use at this position...
216 TypeContext it = stack[currentIndex];
218 if (it == null) {
219 it = new TypeContext();
220 stack[currentIndex] = it;
221 }
223 // Set the context object...
225 it.set(newCode,element);
227 // Trace...
229 traceln(toTrialString(it));
231 // Return...
233 return it;
234 }
236 /**
237 * Pop an element from the stack.
238 * @return the new current element or null if top.
239 */
240 public TypeContext pop (boolean wasValid) {
242 if (currentIndex < 0) {
243 throw new CompilerError("Nothing on stack!");
244 }
246 newCode = stack[currentIndex].getCode();
247 traceln(toResultString(stack[currentIndex],wasValid,false));
249 Type last = stack[currentIndex].getCandidateType();
250 if (last != null) {
252 // Set status...
254 if (wasValid) {
255 last.setStatus(Constants.STATUS_VALID);
256 } else {
257 last.setStatus(Constants.STATUS_INVALID);
258 }
259 }
261 currentIndex--;
263 if (currentIndex < 0) {
265 // Done parsing, so update the invalid types
266 // if this type was valid...
268 if (wasValid) {
269 Type.updateAllInvalidTypes(this);
270 }
271 return null;
272 } else {
273 return stack[currentIndex];
274 }
275 }
277 /**
278 * Get the current size.
279 */
280 public int size () {
281 return currentIndex + 1;
282 }
284 /**
285 * Get a specific context.
286 */
287 public TypeContext getContext (int index) {
289 if (currentIndex < index) {
290 throw new Error("Index out of range");
291 }
292 return stack[index];
293 }
295 /**
296 * Get the current top context.
297 */
298 public TypeContext getContext () {
300 if (currentIndex < 0) {
301 throw new Error("Nothing on stack!");
302 }
303 return stack[currentIndex];
304 }
306 /**
307 * Is parent context a value type?
308 */
309 public boolean isParentAValue () {
311 if (currentIndex > 0) {
312 return stack[currentIndex - 1].isValue();
313 } else {
314 return false;
315 }
316 }
318 /**
319 * Get parent context. Null if none.
320 */
321 public TypeContext getParentContext () {
323 if (currentIndex > 0) {
324 return stack[currentIndex - 1];
325 } else {
326 return null;
327 }
328 }
330 /**
331 * Get a string for the context name...
332 */
333 public String getContextCodeString () {
335 if (currentIndex >= 0) {
336 return CODE_NAMES[newCode];
337 } else {
338 return CODE_NAMES[0];
339 }
340 }
342 /**
343 * Get a string for the given context code...
344 */
345 public static String getContextCodeString (int contextCode) {
346 return CODE_NAMES[contextCode];
347 }
349 private String toTrialString(TypeContext it) {
350 int code = it.getCode();
351 if (code != METHOD && code != MEMBER) {
352 return it.toString() + " (trying " + it.getTypeDescription() + ")";
353 } else {
354 return it.toString();
355 }
356 }
358 private String toResultString (TypeContext it, boolean result, boolean preExisting) {
359 int code = it.getCode();
360 if (code != METHOD && code != MEMBER) {
361 if (result) {
362 String str = it.toString() + " --> " + it.getTypeDescription();
363 if (preExisting) {
364 return str + " [Previously mapped]";
365 } else {
366 return str;
367 }
368 }
369 } else {
370 if (result) {
371 return it.toString() + " --> [Mapped]";
372 }
373 }
374 return it.toString() + " [Did not map]";
375 }
377 public void clear () {
378 for (int i = 0; i < stack.length; i++) {
379 if (stack[i] != null) stack[i].destroy();
380 }
381 }
382 }
385 class TypeContext {
387 public void set(int code, ContextElement element) {
388 this.code = code;
389 this.element = element;
390 if (element instanceof ValueType) {
391 isValue = true;
392 } else {
393 isValue = false;
394 }
395 }
397 public int getCode() {
398 return code;
399 }
401 public String getName() {
402 return element.getElementName();
403 }
405 public Type getCandidateType() {
406 if (element instanceof Type) {
407 return (Type) element;
408 } else {
409 return null;
410 }
411 }
413 public String getTypeDescription() {
414 if (element instanceof Type) {
415 return ((Type) element).getTypeDescription();
416 } else {
417 return "[unknown type]";
418 }
419 }
421 public String toString () {
422 if (element != null) {
423 return ContextStack.getContextCodeString(code) + element.getElementName();
424 } else {
425 return ContextStack.getContextCodeString(code) + "null";
426 }
427 }
429 public boolean isValue () {
430 return isValue;
431 }
433 public boolean isConstant () {
434 return code == ContextStack.MEMBER_CONSTANT;
435 }
437 public void destroy() {
438 if (element instanceof Type) {
439 ((Type)element).destroy();
440 }
441 element = null;
442 }
444 private int code = 0;
445 private ContextElement element = null;
446 private boolean isValue = false;
447 }