001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.bytecode;
005:
006: import java.io.*;
007:
008: /* Represents the contents of a standard "LocalVariableTable" attribute.
009: * @author Per Bothner
010: */
011:
012: public class LocalVarsAttr extends Attribute {
013: private Method method;
014:
015: /* Map local slot index to the local variable that is there. */
016: Variable[] used;
017: public Scope current_scope;
018: Scope parameter_scope;
019:
020: /** Add a new LocalVarsAttr to a CodeAttr. */
021: public LocalVarsAttr(CodeAttr code) {
022: super ("LocalVariableTable");
023: addToFrontOf(code);
024: method = (Method) code.getContainer();
025: code.locals = this ;
026: }
027:
028: /** Create, but don't link into method.code's attributes list (yet). */
029: public LocalVarsAttr(Method method) {
030: super ("LocalVariableTable");
031: CodeAttr code = method.code;
032: this .method = method;
033: code.locals = this ;
034: }
035:
036: public final Method getMethod() {
037: return method;
038: }
039:
040: public VarEnumerator allVars() {
041: return new VarEnumerator(parameter_scope);
042: }
043:
044: public void enterScope(Scope scope) {
045: scope.linkChild(current_scope);
046: current_scope = scope;
047: CodeAttr code = method.getCode();
048: for (Variable var = scope.firstVar(); var != null; var = var
049: .nextVar()) {
050: if (var.isSimple()) {
051: if (!var.isAssigned())
052: var.allocateLocal(code);
053: else if (used[var.offset] == null)
054: used[var.offset] = var;
055: else if (used[var.offset] != var)
056: throw new Error(
057: "inconsistent local variable assignments for "
058: + var + " != " + used[var.offset]);
059: }
060: }
061: }
062:
063: public final boolean isEmpty() {
064: VarEnumerator vars = allVars();
065: Variable var;
066: while ((var = vars.nextVar()) != null) {
067: if (var.isSimple() && var.name != null)
068: return false;
069: }
070: return true;
071: }
072:
073: public final int getCount() {
074: int local_variable_count = 0;
075: VarEnumerator vars = allVars();
076: Variable var;
077: while ((var = vars.nextVar()) != null) {
078: if (shouldEmit(var))
079: local_variable_count++;
080: }
081: return local_variable_count;
082: }
083:
084: public final int getLength() {
085: return 2 + 10 * getCount();
086: }
087:
088: public void assignConstants(ClassType cl) {
089: super .assignConstants(cl);
090:
091: VarEnumerator vars = allVars();
092: Variable var;
093: while ((var = vars.nextVar()) != null) {
094: if (var.isSimple() && var.name != null) {
095: if (var.name_index == 0)
096: var.name_index = cl.getConstants().addUtf8(
097: var.getName()).index;
098: if (var.signature_index == 0)
099: var.signature_index = cl.getConstants().addUtf8(
100: var.getType().signature).index;
101: }
102: }
103: }
104:
105: private boolean shouldEmit(Variable var) {
106: return (var.isSimple() && var.name != null && var.start_pc >= 0 && var.end_pc > var.start_pc);
107: }
108:
109: public void write(DataOutputStream dstr) throws java.io.IOException {
110: VarEnumerator vars = allVars();
111: Variable var;
112: dstr.writeShort(getCount());
113:
114: for (vars.reset(); (var = vars.nextVar()) != null;) {
115: if (shouldEmit(var)) {
116: dstr.writeShort(var.start_pc);
117: dstr.writeShort(var.end_pc - var.start_pc);
118: dstr.writeShort(var.name_index);
119: dstr.writeShort(var.signature_index);
120: dstr.writeShort(var.offset);
121: }
122: }
123: }
124:
125: public void print(ClassTypeWriter dst) {
126: VarEnumerator vars = allVars();
127: dst.print("Attribute \"");
128: dst.print(getName());
129: dst.print("\", length:");
130: dst.print(getLength());
131: dst.print(", count: ");
132: dst.println(getCount());
133:
134: Variable var;
135: for (vars.reset(); (var = vars.nextVar()) != null;) {
136: if (var.isSimple() && var.name != null) {
137: dst.print(" slot#");
138: dst.print(var.offset);
139: dst.print(": name: ");
140: dst.printOptionalIndex(var.name_index);
141: dst.print(var.getName());
142: dst.print(", type: ");
143: dst.printOptionalIndex(var.signature_index);
144: dst.printSignature(var.getType());
145: dst.print(" (pc: ");
146: dst.print(var.start_pc);
147: dst.print(" length: ");
148: dst.print(var.end_pc - var.start_pc);
149: dst.println(')');
150: }
151: }
152: }
153: }
|