001: /*
002: * Copyright 2004 Brian S O'Neill
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.cojen.classfile;
018:
019: import java.util.Arrays;
020: import java.util.HashMap;
021: import java.util.Map;
022: import java.util.Set;
023: import java.io.PrintWriter;
024:
025: /**
026: * CodeAssembler implementation that prints out instructions using a Java-like
027: * syntax that matches the methods of CodeAssembler. When used in conjunction
028: * with a {@link CodeDisassembler}, this class makes it easier to understand
029: * how to use a CodeAssembler.
030: *
031: * @author Brian S O'Neill
032: */
033: public class CodeAssemblerPrinter extends AbstractCodeAssembler
034: implements CodeAssembler {
035: private final LocalVariable[] mParams;
036: private final boolean mIsStatic;
037: private final PrintWriter mWriter;
038: private final String mLinePrefix;
039: private final String mLineSuffix;
040: private final String mBulder;
041:
042: private boolean mNeedSeparatorLine;
043:
044: private int mLocalCounter;
045: private int mLabelCounter;
046:
047: private int mTypeDescCounter;
048: // Maps TypeDesc objects to String variable names.
049: private Map mTypeDescNames;
050:
051: private int mTypeDescArrayCounter;
052: // Maps TypeDesc arrays to String variable names.
053: private Map mTypeDescArrayNames;
054:
055: public CodeAssemblerPrinter(TypeDesc[] paramTypes,
056: boolean isStatic, PrintWriter writer) {
057: this (paramTypes, isStatic, writer, null, null, null);
058: }
059:
060: /**
061: * @param linePrefix optional prefix for each line
062: * @param lineSuffix optional suffix for each line
063: * @param builder when specified, generated method calls are invoked on
064: * local variable by this name
065: */
066: public CodeAssemblerPrinter(TypeDesc[] paramTypes,
067: boolean isStatic, PrintWriter writer, String linePrefix,
068: String lineSuffix, String builder) {
069: mIsStatic = isStatic;
070: mWriter = writer;
071: mLinePrefix = linePrefix;
072: mLineSuffix = lineSuffix;
073: if (builder == null || builder.length() == 0) {
074: builder = "";
075: } else if (!builder.endsWith(".")) {
076: builder += '.';
077: }
078: mBulder = builder;
079: mTypeDescNames = new HashMap();
080: mTypeDescArrayNames = new HashMap();
081:
082: mParams = new LocalVariable[paramTypes.length];
083:
084: int varNum = (isStatic) ? 0 : 1;
085: for (int i = 0; i < paramTypes.length; i++) {
086: String varName = "var_" + (++mLocalCounter);
087: println("LocalVariable " + varName + " = " + mBulder
088: + "getParameter(" + i + ')');
089: LocalVariable localVar = new NamedLocal(varName,
090: paramTypes[i], varNum);
091: varNum += (localVar.isDoubleWord() ? 2 : 1);
092: mParams[i] = localVar;
093: }
094: }
095:
096: public int getParameterCount() {
097: return mParams.length;
098: }
099:
100: public LocalVariable getParameter(int index) {
101: return mParams[index];
102: }
103:
104: public LocalVariable createLocalVariable(String name, TypeDesc type) {
105: String varName = "var_" + (++mLocalCounter);
106: if (name != null) {
107: name = '"' + name + '"';
108: }
109: println("LocalVariable " + varName + " = " + mBulder
110: + "createLocalVariable(" + name + ", "
111: + getTypeDescName(type) + ')');
112: return new NamedLocal(varName, type, -1);
113: }
114:
115: public Label createLabel() {
116: String name = "label_" + (++mLabelCounter);
117: println("Label " + name + " = " + mBulder + "createLabel()");
118: return new NamedLabel(name);
119: }
120:
121: public void exceptionHandler(Location startLocation,
122: Location endLocation, String catchClassName) {
123: println(mBulder
124: + "exceptionHandler("
125: + getLabelName(startLocation)
126: + ", "
127: + getLabelName(endLocation)
128: + ", "
129: + (catchClassName == null ? "null"
130: : ('"' + catchClassName + '"')) + ')');
131: }
132:
133: public void mapLineNumber(int lineNumber) {
134: separatorLine();
135: println(mBulder + "mapLineNumber(" + lineNumber + ')');
136: }
137:
138: public void loadNull() {
139: println(mBulder + "loadNull()");
140: }
141:
142: public void loadConstant(String value) {
143: if (value == null) {
144: loadNull();
145: } else {
146: println(mBulder + "loadConstant(\"" + escape(value) + "\")");
147: }
148: }
149:
150: public void loadConstant(TypeDesc type) {
151: if (type == null) {
152: loadNull();
153: } else {
154: println(mBulder + "loadConstant(" + getTypeDescName(type)
155: + ')');
156: }
157:
158: }
159:
160: public void loadConstant(boolean value) {
161: println(mBulder + "loadConstant(" + value + ')');
162: }
163:
164: public void loadConstant(int value) {
165: println(mBulder + "loadConstant(" + value + ')');
166: }
167:
168: public void loadConstant(long value) {
169: println(mBulder + "loadConstant(" + value + "L)");
170: }
171:
172: public void loadConstant(float value) {
173: String str;
174: if (value != value) {
175: str = "0.0f/0.0f";
176: } else if (value == Float.NEGATIVE_INFINITY) {
177: str = "-1.0f/0.0f";
178: } else if (value == Float.POSITIVE_INFINITY) {
179: str = "1.0f/0.0f";
180: } else {
181: str = String.valueOf(value) + 'f';
182: }
183: println(mBulder + "loadConstant(" + str + ")");
184: }
185:
186: public void loadConstant(double value) {
187: String str;
188: if (value != value) {
189: str = "0.0d/0.0d";
190: } else if (value == Double.NEGATIVE_INFINITY) {
191: str = "-1.0d/0.0d";
192: } else if (value == Double.POSITIVE_INFINITY) {
193: str = "1.0d/0.0d";
194: } else {
195: str = String.valueOf(value) + 'd';
196: }
197: println(mBulder + "loadConstant(" + str + ")");
198: }
199:
200: public void loadLocal(LocalVariable local) {
201: println(mBulder + "loadLocal(" + local.getName() + ')');
202: }
203:
204: public void loadThis() {
205: println(mBulder + "loadThis()");
206: }
207:
208: public void storeLocal(LocalVariable local) {
209: println(mBulder + "storeLocal(" + local.getName() + ')');
210: }
211:
212: public void loadFromArray(TypeDesc type) {
213: println(mBulder + "loadFromArray(" + getTypeDescName(type)
214: + ')');
215: }
216:
217: public void storeToArray(TypeDesc type) {
218: println(mBulder + "storeToArray(" + getTypeDescName(type) + ')');
219: }
220:
221: public void loadField(String fieldName, TypeDesc type) {
222: println(mBulder + "loadField(\"" + fieldName + "\", "
223: + getTypeDescName(type) + ')');
224: }
225:
226: public void loadField(String className, String fieldName,
227: TypeDesc type) {
228: println(mBulder + "loadField(\"" + className + "\", \""
229: + fieldName + "\", " + getTypeDescName(type) + ')');
230: }
231:
232: public void loadField(TypeDesc classDesc, String fieldName,
233: TypeDesc type) {
234: println(mBulder + "loadField(\"" + getTypeDescName(classDesc)
235: + "\", \"" + fieldName + "\", " + getTypeDescName(type)
236: + ')');
237: }
238:
239: public void loadStaticField(String fieldName, TypeDesc type) {
240: println(mBulder + "loadStaticField(\"" + fieldName + "\", "
241: + getTypeDescName(type) + ')');
242: }
243:
244: public void loadStaticField(String className, String fieldName,
245: TypeDesc type) {
246: println(mBulder + "loadStaticField(\"" + className + "\", \""
247: + fieldName + "\", " + getTypeDescName(type) + ')');
248: }
249:
250: public void loadStaticField(TypeDesc classDesc, String fieldName,
251: TypeDesc type) {
252: println(mBulder + "loadStaticField(\""
253: + getTypeDescName(classDesc) + "\", \"" + fieldName
254: + "\", " + getTypeDescName(type) + ')');
255: }
256:
257: public void storeField(String fieldName, TypeDesc type) {
258: println(mBulder + "storeField(\"" + fieldName + "\", "
259: + getTypeDescName(type) + ')');
260: }
261:
262: public void storeField(String className, String fieldName,
263: TypeDesc type) {
264: println(mBulder + "storeField(\"" + className + "\", \""
265: + fieldName + "\", " + getTypeDescName(type) + ')');
266: }
267:
268: public void storeField(TypeDesc classDesc, String fieldName,
269: TypeDesc type) {
270: println(mBulder + "storeField(\"" + getTypeDescName(classDesc)
271: + "\", \"" + fieldName + "\", " + getTypeDescName(type)
272: + ')');
273: }
274:
275: public void storeStaticField(String fieldName, TypeDesc type) {
276: println(mBulder + "storeStaticField(\"" + fieldName + "\", "
277: + getTypeDescName(type) + ')');
278: }
279:
280: public void storeStaticField(String className, String fieldName,
281: TypeDesc type) {
282: println(mBulder + "storeStaticField(\"" + className + "\", \""
283: + fieldName + "\", " + getTypeDescName(type) + ')');
284: }
285:
286: public void storeStaticField(TypeDesc classDesc, String fieldName,
287: TypeDesc type) {
288: println(mBulder + "storeStaticField(\""
289: + getTypeDescName(classDesc) + "\", \"" + fieldName
290: + "\", " + getTypeDescName(type) + ')');
291: }
292:
293: public void returnVoid() {
294: println(mBulder + "returnVoid()");
295: }
296:
297: public void returnValue(TypeDesc type) {
298: println(mBulder + "returnValue(" + getTypeDescName(type) + ')');
299: }
300:
301: public void convert(TypeDesc fromType, TypeDesc toType) {
302: println(mBulder + "convert(" + getTypeDescName(fromType) + ", "
303: + getTypeDescName(toType) + ')');
304: }
305:
306: public void convert(TypeDesc fromType, TypeDesc toType,
307: int fpConvertMode) {
308: switch (fpConvertMode) {
309: default:
310: convert(fromType, toType);
311: break;
312: case CONVERT_FP_BITS:
313: println(mBulder + "convert(" + getTypeDescName(fromType)
314: + ", " + getTypeDescName(toType) + ", " + mBulder
315: + ".CONVERT_FP_BITS" + ')');
316: break;
317: case CONVERT_FP_RAW_BITS:
318: println(mBulder + "convert(" + getTypeDescName(fromType)
319: + ", " + getTypeDescName(toType) + ", " + mBulder
320: + ".CONVERT_FP_RAW_BITS" + ')');
321: break;
322: }
323: }
324:
325: public void invokeVirtual(String methodName, TypeDesc ret,
326: TypeDesc[] params) {
327: println(mBulder + "invokeVirtual(\"" + methodName + "\", "
328: + getTypeDescName(ret) + ", "
329: + getTypeDescArrayName(params) + ')');
330: }
331:
332: public void invokeVirtual(String className, String methodName,
333: TypeDesc ret, TypeDesc[] params) {
334: println(mBulder + "invokeVirtual(\"" + className + "\", \""
335: + methodName + "\", " + getTypeDescName(ret) + ", "
336: + getTypeDescArrayName(params) + ')');
337: }
338:
339: public void invokeVirtual(TypeDesc classDesc, String methodName,
340: TypeDesc ret, TypeDesc[] params) {
341: println(mBulder + "invokeVirtual(\""
342: + getTypeDescName(classDesc) + "\", \"" + methodName
343: + "\", " + getTypeDescName(ret) + ", "
344: + getTypeDescArrayName(params) + ')');
345: }
346:
347: public void invokeStatic(String methodName, TypeDesc ret,
348: TypeDesc[] params) {
349: println(mBulder + "invokeStatic(\"" + methodName + "\", "
350: + getTypeDescName(ret) + ", "
351: + getTypeDescArrayName(params) + ')');
352: }
353:
354: public void invokeStatic(String className, String methodName,
355: TypeDesc ret, TypeDesc[] params) {
356: println(mBulder + "invokeStatic(\"" + className + "\", \""
357: + methodName + "\", " + getTypeDescName(ret) + ", "
358: + getTypeDescArrayName(params) + ')');
359: }
360:
361: public void invokeStatic(TypeDesc classDesc, String methodName,
362: TypeDesc ret, TypeDesc[] params) {
363: println(mBulder + "invokeStatic(\""
364: + getTypeDescName(classDesc) + "\", \"" + methodName
365: + "\", " + getTypeDescName(ret) + ", "
366: + getTypeDescArrayName(params) + ')');
367: }
368:
369: public void invokeInterface(String className, String methodName,
370: TypeDesc ret, TypeDesc[] params) {
371: println(mBulder + "invokeInterface(\"" + className + "\", \""
372: + methodName + "\", " + getTypeDescName(ret) + ", "
373: + getTypeDescArrayName(params) + ')');
374: }
375:
376: public void invokeInterface(TypeDesc classDesc, String methodName,
377: TypeDesc ret, TypeDesc[] params) {
378: println(mBulder + "invokeInterface(\""
379: + getTypeDescName(classDesc) + "\", \"" + methodName
380: + "\", " + getTypeDescName(ret) + ", "
381: + getTypeDescArrayName(params) + ')');
382: }
383:
384: public void invokePrivate(String methodName, TypeDesc ret,
385: TypeDesc[] params) {
386: println(mBulder + "invokePrivate(\"" + methodName + "\", "
387: + getTypeDescName(ret) + ", "
388: + getTypeDescArrayName(params) + ')');
389: }
390:
391: public void invokeSuper(String super ClassName, String methodName,
392: TypeDesc ret, TypeDesc[] params) {
393: println(mBulder + "invokeSuper(\"" + super ClassName + "\", \""
394: + methodName + "\", " + getTypeDescName(ret) + ", "
395: + getTypeDescArrayName(params) + ')');
396: }
397:
398: public void invokeSuper(TypeDesc super ClassDesc, String methodName,
399: TypeDesc ret, TypeDesc[] params) {
400: println(mBulder + "invokeSuper(\""
401: + getTypeDescName(super ClassDesc) + "\", \""
402: + methodName + "\", " + getTypeDescName(ret) + ", "
403: + getTypeDescArrayName(params) + ')');
404: }
405:
406: public void invokeConstructor(TypeDesc[] params) {
407: println(mBulder + "invokeConstructor("
408: + getTypeDescArrayName(params) + ')');
409: }
410:
411: public void invokeConstructor(String className, TypeDesc[] params) {
412: println(mBulder + "invokeConstructor(\"" + className + "\", "
413: + getTypeDescArrayName(params) + ')');
414: }
415:
416: public void invokeConstructor(TypeDesc classDesc, TypeDesc[] params) {
417: println(mBulder + "invokeConstructor(\""
418: + getTypeDescName(classDesc) + "\", "
419: + getTypeDescArrayName(params) + ')');
420: }
421:
422: public void invokeSuperConstructor(TypeDesc[] params) {
423: println(mBulder + "invokeSuperConstructor("
424: + getTypeDescArrayName(params) + ')');
425: }
426:
427: public void newObject(TypeDesc type) {
428: println(mBulder + "newObject(" + getTypeDescName(type) + ')');
429: }
430:
431: public void newObject(TypeDesc type, int dimensions) {
432: if (dimensions == 0 && !type.isArray()) {
433: newObject(type);
434: } else {
435: println(mBulder + "newObject(" + getTypeDescName(type)
436: + ", " + dimensions + ')');
437: }
438: }
439:
440: public void dup() {
441: println(mBulder + "dup()");
442: }
443:
444: public void dupX1() {
445: println(mBulder + "dupX1()");
446: }
447:
448: public void dupX2() {
449: println(mBulder + "dupX2()");
450: }
451:
452: public void dup2() {
453: println(mBulder + "dup2()");
454: }
455:
456: public void dup2X1() {
457: println(mBulder + "dup2X1()");
458: }
459:
460: public void dup2X2() {
461: println(mBulder + "dup2X2()");
462: }
463:
464: public void pop() {
465: println(mBulder + "pop()");
466: }
467:
468: public void pop2() {
469: println(mBulder + "pop2()");
470: }
471:
472: public void swap() {
473: println(mBulder + "swap()");
474: }
475:
476: public void swap2() {
477: println(mBulder + "swap2()");
478: }
479:
480: public void branch(Location location) {
481: println(mBulder + "branch(" + getLabelName(location) + ')');
482: }
483:
484: public void ifNullBranch(Location location, boolean choice) {
485: println(mBulder + "ifNullBranch(" + getLabelName(location)
486: + ", " + choice + ')');
487: }
488:
489: public void ifEqualBranch(Location location, boolean choice) {
490: println(mBulder + "ifEqualBranch(" + getLabelName(location)
491: + ", " + choice + ')');
492: }
493:
494: public void ifZeroComparisonBranch(Location location, String choice) {
495: println(mBulder + "ifZeroComparisonBranch("
496: + getLabelName(location) + ", \"" + choice + "\")");
497: }
498:
499: public void ifComparisonBranch(Location location, String choice) {
500: println(mBulder + "ifComparisonBranch("
501: + getLabelName(location) + ", \"" + choice + "\")");
502: }
503:
504: public void switchBranch(int[] cases, Location[] locations,
505: Location defaultLocation) {
506:
507: StringBuffer buf = new StringBuffer(cases.length * 15);
508:
509: buf.append(mBulder + "switchBranch(");
510:
511: buf.append("new int[] {");
512: for (int i = 0; i < cases.length; i++) {
513: if (i > 0) {
514: buf.append(", ");
515: }
516: buf.append(cases[i]);
517: }
518: buf.append("}");
519:
520: buf.append(", ");
521:
522: buf.append("new Location[] {");
523: for (int i = 0; i < locations.length; i++) {
524: if (i > 0) {
525: buf.append(", ");
526: }
527: buf.append(getLabelName(locations[i]));
528: }
529: buf.append("}");
530:
531: buf.append(", ");
532: buf.append(getLabelName(defaultLocation));
533: buf.append(')');
534:
535: println(buf.toString());
536: }
537:
538: public void jsr(Location location) {
539: println(mBulder + "jsr(" + getLabelName(location) + ')');
540: }
541:
542: public void ret(LocalVariable local) {
543: println(mBulder + "ret(" + local.getName() + ')');
544: }
545:
546: public void math(byte opcode) {
547: println(mBulder + "math(Opcode."
548: + Opcode.getMnemonic(opcode).toUpperCase() + ')');
549: }
550:
551: public void arrayLength() {
552: println(mBulder + "arrayLength()");
553: }
554:
555: public void throwObject() {
556: println(mBulder + "throwObject()");
557: }
558:
559: public void checkCast(TypeDesc type) {
560: println(mBulder + "checkCast(" + getTypeDescName(type) + ')');
561: }
562:
563: public void instanceOf(TypeDesc type) {
564: println(mBulder + "instanceOf(" + getTypeDescName(type) + ')');
565: }
566:
567: public void integerIncrement(LocalVariable local, int amount) {
568: println(mBulder + "integerIncrement(" + local.getName() + ", "
569: + amount + ')');
570: }
571:
572: public void monitorEnter() {
573: println(mBulder + "monitorEnter()");
574: }
575:
576: public void monitorExit() {
577: println(mBulder + "monitorExit()");
578: }
579:
580: public void nop() {
581: println(mBulder + "nop()");
582: }
583:
584: public void breakpoint() {
585: println(mBulder + "breakpoint()");
586: }
587:
588: private void separatorLine() {
589: if (mNeedSeparatorLine) {
590: mWriter.println();
591: mNeedSeparatorLine = false;
592: }
593: }
594:
595: private void println(String str) {
596: mNeedSeparatorLine = true;
597: if (mLinePrefix != null) {
598: mWriter.print(mLinePrefix);
599: }
600: if (mLineSuffix == null) {
601: mWriter.println(str);
602: } else {
603: mWriter.print(str);
604: mWriter.println(mLineSuffix);
605: }
606: }
607:
608: private String getLabelName(Location location) {
609: if (location instanceof NamedLabel) {
610: return ((NamedLabel) location).mName;
611: } else {
612: return ((NamedLabel) createLabel()).mName;
613: }
614: }
615:
616: private String getTypeDescName(TypeDesc type) {
617: if (type == null) {
618: return "null";
619: }
620:
621: String name = (String) mTypeDescNames.get(type);
622:
623: if (name == null) {
624: if (type.isPrimitive()) {
625: name = "TypeDesc.".concat(type.getRootName()
626: .toUpperCase());
627: mTypeDescNames.put(type, name);
628: return name;
629: } else if (type == TypeDesc.OBJECT) {
630: mTypeDescNames.put(type, name = "TypeDesc.OBJECT");
631: return name;
632: } else if (type == TypeDesc.STRING) {
633: mTypeDescNames.put(type, name = "TypeDesc.STRING");
634: return name;
635: }
636:
637: name = "type_" + (++mTypeDescCounter);
638: mTypeDescNames.put(type, name);
639:
640: StringBuffer buf = new StringBuffer("TypeDesc ");
641: buf.append(name);
642: buf.append(" = ");
643:
644: TypeDesc componentType = type.getComponentType();
645: if (componentType != null) {
646: buf.append(getTypeDescName(componentType));
647: buf.append(".toArrayType(");
648: } else {
649: buf.append("TypeDesc.forClass(");
650: buf.append('"');
651: buf.append(type.getRootName());
652: buf.append('"');
653: }
654:
655: buf.append(')');
656: println(buf.toString());
657: }
658:
659: return name;
660: }
661:
662: private String getTypeDescArrayName(TypeDesc[] types) {
663: if (types == null) {
664: return "null";
665: }
666:
667: Object key = Arrays.asList(types);
668: String name = (String) mTypeDescArrayNames.get(key);
669:
670: if (name == null) {
671: name = "params_" + (++mTypeDescArrayCounter);
672: mTypeDescArrayNames.put(key, name);
673:
674: StringBuffer buf = new StringBuffer("TypeDesc[] ");
675: buf.append(name);
676: buf.append(" = new TypeDesc[] {");
677:
678: for (int i = 0; i < types.length; i++) {
679: if (i > 0) {
680: buf.append(", ");
681: }
682: buf.append(getTypeDescName(types[i]));
683: }
684:
685: buf.append('}');
686: println(buf.toString());
687: }
688:
689: return name;
690: }
691:
692: static String escape(String value) {
693: return escape(value, false);
694: }
695:
696: static String escape(String value, boolean forChar) {
697: int length = value.length();
698: int i = 0;
699: for (; i < length; i++) {
700: char c = value.charAt(i);
701: if (c < 32 || c > 126 || c == '"' || c == '\\'
702: || (forChar && c == '\'')) {
703: break;
704: }
705: }
706:
707: if (i >= length) {
708: return value;
709: }
710:
711: StringBuffer buf = new StringBuffer(length + 16);
712: for (i = 0; i < length; i++) {
713: char c = value.charAt(i);
714: if (c >= 32 && c <= 126 && c != '"' && c != '\\'
715: && (!forChar || c != '\'')) {
716: buf.append(c);
717: continue;
718: }
719:
720: switch (c) {
721: case '\0':
722: buf.append("\\0");
723: break;
724: case '"':
725: buf.append("\\\"");
726: break;
727: case '\'':
728: buf.append("\\'");
729: break;
730: case '\\':
731: buf.append("\\\\");
732: break;
733: case '\b':
734: buf.append("\\b");
735: break;
736: case '\f':
737: buf.append("\\f");
738: break;
739: case '\n':
740: buf.append("\\n");
741: break;
742: case '\r':
743: buf.append("\\r");
744: break;
745: case '\t':
746: buf.append("\\t");
747: break;
748: default:
749: String u = Integer.toHexString(c).toLowerCase();
750: buf.append("\\u");
751: for (int len = u.length(); len < 4; len++) {
752: buf.append('0');
753: }
754: buf.append(u);
755: break;
756: }
757: }
758:
759: return buf.toString();
760: }
761:
762: private class NamedLocal implements LocalVariable {
763: private final String mName;
764: private final TypeDesc mType;
765: private final int mNumber;
766:
767: public NamedLocal(String name, TypeDesc type, int number) {
768: mName = name;
769: mType = type;
770: mNumber = number;
771: }
772:
773: public String getName() {
774: return mName;
775: }
776:
777: public void setName(String name) {
778: println(mName + ".setName(" + name + ')');
779: }
780:
781: public TypeDesc getType() {
782: return mType;
783: }
784:
785: public boolean isDoubleWord() {
786: return mType.isDoubleWord();
787: }
788:
789: public int getNumber() {
790: return mNumber;
791: }
792:
793: public Location getStartLocation() {
794: return null;
795: }
796:
797: public Location getEndLocation() {
798: return null;
799: }
800:
801: public Set getLocationRangeSet() {
802: return null;
803: }
804: }
805:
806: private class NamedLabel implements Label {
807: public final String mName;
808:
809: public NamedLabel(String name) {
810: mName = name;
811: }
812:
813: public Label setLocation() {
814: println(mName + ".setLocation()");
815: return this ;
816: }
817:
818: public int getLocation() {
819: return -1;
820: }
821:
822: public int compareTo(Object obj) {
823: return 0;
824: }
825: }
826: }
|