1 /*
2 * Copyright (c) 1996, 2020, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.asmtools.jasm;
24
25 import java.io.PrintWriter;
26 import java.util.HashMap;
27
28 /**
29 *
30 * Tables
31 *
32 * The classes in Tables are following a Singleton Pattern. These classes are Enums, and
33 * they are contained in private hash maps (lookup tables and reverse lookup tables).
34 * These hash maps all have public accessors, which clients use to look-up enums.
35 *
36 * Tokens in this table carry no external state, and are typically treated as constants.
37 * They do not need to be reset.
38 *
39 */
40 public class Tables {
41
42 public static final int JAVA_MAGIC = 0xCAFEBABE;
43 /**
44 * Lookup-tables for various types.
45 */
46 private static HashMap<String, AttrTag> NameToAttrTag = new HashMap<>(9);
47 private static HashMap<Integer, AttrTag> AttrTags = new HashMap<>(9);
48
49 private static HashMap<String, SubTag> NameToSubTag = new HashMap<>(9);
50 private static HashMap<Integer, SubTag> SubTags = new HashMap<>(9);
51
52 private static HashMap<String, BasicType> NameToBasicType = new HashMap<>(10);
53 private static HashMap<Integer, BasicType> BasicTypes = new HashMap<>(10);
54
55 private static HashMap<String, AnnotElemType> NameToAnnotElemType = new HashMap<>(10);
56 private static HashMap<Character, AnnotElemType> AnnotElemTypes = new HashMap<>(10);
57
58 private static HashMap<String, StackMapType> KeyToStackMapType = new HashMap<>(10);
59 private static HashMap<String, StackMapType> NameToStackMapType = new HashMap<>(10);
60 private static HashMap<Integer, StackMapType> StackMapTypes = new HashMap<>(10);
61
62 private static HashMap<String, StackMapFrameType> NameToStackMapFrameType = new HashMap<>(10);
63 private static HashMap<Integer, StackMapFrameType> StackMapFrameTypes = new HashMap<>(10);
64
65 private static HashMap<String, ConstType> NameToConstantType = new HashMap<>(ConstType.maxTag);
66 private static HashMap<Integer, ConstType> ConstantTypes = new HashMap<>(ConstType.maxTag);
67
68 static {
69 // register all of the tokens
70 for (ConstType ct : ConstType.values()) {
71 registerConstantType(ct);
72 }
73
74 /* Type codes for SubTags */
75 for (AttrTag at : AttrTag.values()) {
76 registerAttrtag(at);
77 }
78
79 /* Type codes for SubTags */
80 for (SubTag st : SubTag.values()) {
81 registerSubtag(st);
82 }
83
84 /* Type codes for BasicTypes */
85 for (BasicType bt : BasicType.values()) {
86 registerBasicType(bt);
87 }
88
89 /* Type codes for BasicTypes */
90 for (AnnotElemType aet : AnnotElemType.values()) {
91 registerAnnotElemType(aet);
92 }
93
94 /* Type codes for StackMapTypes */
95 for (StackMapType smt : StackMapType.values()) {
96 registerStackMapType(smt);
97 }
98
99 /* Type codes for StackMapFrame attribute */
100 for (StackMapFrameType smft : StackMapFrameType.values()) {
101 registerStackMapFrameType(smft);
102 }
103
104 }
105
106 /**
107 * ConstType
108 *
109 * A (typed) tag (constant) representing the type of Constant in the Constant Pool.
110 */
111 static public enum ConstType {
112 CONSTANT_ZERO (-3, "CONSTANT_ZERO", ""),
113 CONSTANT_UTF8 (1, "CONSTANT_UTF8", "Asciz"),
114 CONSTANT_UNICODE (2, "CONSTANT_UNICODE", ""),
115 CONSTANT_INTEGER (3, "CONSTANT_INTEGER", "int"),
116 CONSTANT_FLOAT (4, "CONSTANT_FLOAT", "float"),
117 CONSTANT_LONG (5, "CONSTANT_LONG", "long"),
118 CONSTANT_DOUBLE (6, "CONSTANT_DOUBLE", "double"),
119 CONSTANT_CLASS (7, "CONSTANT_CLASS", "class"),
120 CONSTANT_STRING (8, "CONSTANT_STRING", "String"),
121 CONSTANT_FIELD (9, "CONSTANT_FIELD", "Field"),
122 CONSTANT_METHOD (10, "CONSTANT_METHOD", "Method"),
123 CONSTANT_INTERFACEMETHOD (11, "CONSTANT_INTERFACEMETHOD", "InterfaceMethod"),
124 CONSTANT_NAMEANDTYPE (12, "CONSTANT_NAMEANDTYPE", "NameAndType"),
125 // Constant 13 reserved
126 // Constant 14 reserved
127 CONSTANT_METHODHANDLE (15, "CONSTANT_METHODHANDLE", "MethodHandle"),
128 CONSTANT_METHODTYPE (16, "CONSTANT_METHODTYPE", "MethodType"),
129 CONSTANT_DYNAMIC (17, "CONSTANT_DYNAMIC", "Dynamic"),
130 CONSTANT_INVOKEDYNAMIC (18, "CONSTANT_INVOKEDYNAMIC", "InvokeDynamic"),
131 CONSTANT_MODULE (19, "CONSTANT_MODULE", "Module"),
132 CONSTANT_PACKAGE (20, "CONSTANT_PACKAGE", "Package");
133
134 static final public int maxTag = 20;
135
136 private final int value;
137 private final String parseKey;
138 private final String printval;
139
140 ConstType(int val, String print, String parse) {
141 value = val;
142 parseKey = parse;
143 printval = print;
144 }
145
146 public int value() {
147 return value;
148 }
149
150 public String parseKey() {
151 return parseKey;
152 }
153
154 public String printval() {
155 return printval;
156 }
157
158 public void print(PrintWriter out) {
159 out.print(parseKey);
160 }
161
162 @Override
163 public String toString() {
164 return "<" + printval + "> [" + Integer.toString(value) + "]";
165 }
166 };
167
168 static public ConstType tag(int i) {
169 return ConstantTypes.get(i);
170 }
171
172 static public ConstType tag(String parsekey) {
173 return NameToConstantType.get(parsekey);
174 }
175
176 private static void registerConstantType(ConstType tt) {
177 NameToConstantType.put(tt.parseKey, tt);
178 ConstantTypes.put(tt.value, tt);
179 }
180
181 /**
182 * Attribute descriptor enums
183 */
184 static public enum AttrTag {
185
186 // Constant for ME Spec (StackMap does not appear in SE VM Spec)
187 ATT_Unrecognized (0, "ATT_Unrecognized", ""),
188 ATT_StackMap (1, "ATT_StackMap", "StackMap"),
189 // Numbers corespond to VM spec (chapter 4.7.X)
190 ATT_ConstantValue (2, "ATT_ConstantValue", "ConstantValue"),
191 ATT_Code (3, "ATT_Code", "Code"),
192 ATT_StackMapTable (4, "ATT_StackMapTable", "StackMapTable"),
193 ATT_Exceptions (5, "ATT_Exceptions", "Exceptions"),
194 ATT_InnerClasses (6, "ATT_InnerClasses", "InnerClasses"),
195 ATT_EnclosingMethod (7, "ATT_EnclosingMethod", "EnclosingMethod"),
196 ATT_Synthetic (8, "ATT_Synthetic", "Synthetic"),
197 ATT_Signature (9, "ATT_Signature", "Signature"),
198 ATT_SourceFile (10, "ATT_SourceFile", "SourceFile"),
199 ATT_SourceDebugExtension (11, "ATT_SourceDebugExtension", "SourceDebugExtension"),
200 ATT_LineNumberTable (12, "ATT_LineNumberTable", "LineNumberTable"),
201 ATT_LocalVariableTable (13, "ATT_LocalVariableTable", "LocalVariableTable"),
202 ATT_LocalVariableTypeTable (14, "ATT_LocalVariableTypeTable", "LocalVariableTypeTable"),
203 ATT_Deprecated (15, "ATT_Deprecated", "Deprecated"),
204 ATT_RuntimeVisibleAnnotations (16, "ATT_RuntimeVisibleAnnotations", "RuntimeVisibleAnnotations"),
205 ATT_RuntimeInvisibleAnnotations (17, "ATT_RuntimeInvisibleAnnotations", "RuntimeInvisibleAnnotations"),
206 ATT_RuntimeVisibleParameterAnnotations (18, "ATT_RuntimeVisibleParameterAnnotations", "RuntimeVisibleParameterAnnotations"),
207 ATT_RuntimeInvisibleParameterAnnotations (19, "ATT_RuntimeInvisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations"),
208 ATT_AnnotationDefault (20, "ATT_AnnotationDefault", "AnnotationDefault"),
209 ATT_BootstrapMethods (21, "ATT_BootstrapMethods", "BootstrapMethods"),
210 ATT_RuntimeVisibleTypeAnnotations (22, "ATT_RuntimeVisibleTypeAnnotations", "RuntimeVisibleTypeAnnotations"),
211 ATT_RuntimeInvisibleTypeAnnotations (23, "ATT_RuntimeInvisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations"),
212 ATT_MethodParameters (24, "ATT_MethodParameters", "MethodParameters"),
213 ATT_Module (25, "ATT_Module", "Module"),
214 ATT_Version (26, "ATT_Version", "Version"),
215 ATT_TargetPlatform (27, "ATT_TargetPlatform", "TargetPlatform"),
216 ATT_MainClass (28, "ATT_MainClass", "MainClass"),
217 ATT_ModulePackages (29, "ATT_ModulePackages", "ModulePackages"),
218 ATT_ModuleMainClass (30, "ATT_ModuleMainClass", "ModuleMainClass"),
219 ATT_ModuleTarget (31, "ATT_ModuleTarget", "ModuleTarget"),
220 // JEP 181: class file 55.0
221 ATT_NestHost (32, "ATT_NestHost", "NestHost"),
222 ATT_NestMembers (33, "ATT_NestMembers", "NestMembers"),
223 // JEP 359 Record(Preview): class file 58.65535
224 // Record_attribute {
225 // u2 attribute_name_index;
226 // u4 attribute_length;
227 // u2 components_count;
228 // component_info components[components_count];
229 // }
230 ATT_Record (34, "ATT_Record", "Record"),
231 // JEP 360 (Sealed types): class file 59.65535
232 // PermittedSubclasses_attribute {
233 // u2 attribute_name_index;
234 // u4 attribute_length;
235 // u2 number_of_classes;
236 // u2 classes[number_of_classes];
237 // }
238 ATT_PermittedSubclasses (35, "ATT_PermittedSubclasses", "PermittedSubclasses"),
239 ATT_Preload (36, "ATT_Preload", "Preload");
240
241 private final Integer value;
242 private final String printval;
243 private final String parsekey;
244
245 AttrTag(Integer val, String print, String parse) {
246 value = val;
247 printval = print;
248 parsekey = parse;
249 }
250
251 public String printval() {
252 return printval;
253 }
254
255 public String parsekey() {
256 return parsekey;
257 }
258 }
259
260 private static void registerAttrtag(AttrTag tg) {
261 NameToAttrTag.put(tg.parsekey, tg);
262 AttrTags.put(tg.value, tg);
263 }
264
265 public static AttrTag attrtag(int val) {
266 AttrTag tg = AttrTags.get(val);
267 if (tg == null) {
268 tg = AttrTag.ATT_Unrecognized;
269 }
270 return tg;
271 }
272
273 public static AttrTag attrtag(String idValue) {
274 AttrTag tg = NameToAttrTag.get(idValue);
275 if (tg == null) {
276 tg = AttrTag.ATT_Unrecognized;
277 }
278 return tg;
279 }
280
281 public static String attrtagName(int subtag) {
282 AttrTag tg = AttrTags.get(subtag);
283 return tg.parsekey;
284 }
285
286 public static int attrtagValue(String idValue) {
287 AttrTag tg = attrtag(idValue);
288 return tg.value;
289 }
290
291
292 /*-------------------------------------------------------- */
293 /**
294 * SubTag enums
295 */
296 static public enum SubTag {
297 REF_GETFIELD (1, "REF_getField"),
298 REF_GETSTATIC (2, "REF_getStatic"),
299 REF_PUTFIELD (3, "REF_putField"),
300 REF_PUTSTATIC (4, "REF_putStatic"),
301 REF_INVOKEVIRTUAL (5, "REF_invokeVirtual"),
302 REF_INVOKESTATIC (6, "REF_invokeStatic"),
303 REF_INVOKESPECIAL (7, "REF_invokeSpecial"),
304 REF_NEWINVOKESPECIAL (8, "REF_newInvokeSpecial"),
305 REF_INVOKEINTERFACE (9, "REF_invokeInterface");
306
307 private final Integer value;
308 private final String printval;
309
310 SubTag(Integer val, String print) {
311 value = val;
312 printval = print;
313 }
314
315 public String printval() {
316 return printval;
317 }
318
319 public Integer value() {
320 return value;
321 }
322 }
323
324 private static void registerSubtag(SubTag tg) {
325 NameToSubTag.put(tg.printval, tg);
326 SubTags.put(tg.value, tg);
327 }
328
329 public static SubTag subtag(String subtag) {
330 return NameToSubTag.get(subtag);
331 }
332
333 public static SubTag subtag(int subtag) {
334 return SubTags.get(subtag);
335 }
336
337 public static String subtagName(int subtag) {
338 String retval = null;
339 SubTag tg = SubTags.get(subtag);
340 if (tg != null) {
341 retval = tg.printval;
342 }
343 return retval;
344 }
345
346 public static int subtagValue(String idValue) {
347 int retval = 0;
348 SubTag tg = NameToSubTag.get(idValue);
349 if (tg != null) {
350 retval = tg.value;
351 }
352 return retval;
353 }
354
355 /*-------------------------------------------------------- */
356 /**
357 * BasicType enums
358 */
359 static public enum BasicType {
360 T_INT (0x0000000a, "int"),
361 T_LONG (0x0000000b, "long"),
362 T_FLOAT (0x00000006, "float"),
363 T_DOUBLE (0x00000007, "double"),
364 T_CLASS (0x00000002, "class"),
365 T_BOOLEAN (0x00000004, "boolean"),
366 T_CHAR (0x00000005, "char"),
367 T_BYTE (0x00000008, "byte"),
368 T_SHORT (0x00000009, "short");
369
370 private final Integer value;
371 private final String printval;
372
373 BasicType(Integer val, String print) {
374 value = val;
375 printval = print;
376 }
377
378 public String printval() {
379 return printval;
380 }
381 }
382
383 private static void registerBasicType(BasicType typ) {
384 NameToBasicType.put(typ.printval, typ);
385 BasicTypes.put(typ.value, typ);
386 }
387
388 public static BasicType basictype(String idValue) {
389 return NameToBasicType.get(idValue);
390 }
391
392 public static BasicType basictype(int subtag) {
393 return BasicTypes.get(subtag);
394 }
395
396 public static String basictypeName(int subtag) {
397 String retval = null;
398 BasicType tg = BasicTypes.get(subtag);
399 if (tg != null) {
400 retval = tg.printval;
401 }
402 return retval;
403 }
404
405 public static int basictypeValue(String idValue) {
406 int retval = -1;
407 BasicType tg = NameToBasicType.get(idValue);
408 if (tg != null) {
409 retval = tg.value;
410 }
411 return retval;
412 }
413
414 /*-------------------------------------------------------- */
415 /**
416 * AnnotElemType enums
417 */
418 static public enum AnnotElemType {
419
420 AE_BYTE ('B', "byte"),
421 AE_CHAR ('C', "char"),
422 AE_SHORT ('S', "short"),
423 AE_INT ('I', "int"),
424 AE_LONG ('J', "long"),
425 AE_FLOAT ('F', "float"),
426 AE_DOUBLE ('D', "double"),
427 AE_BOOLEAN ('Z', "boolean"),
428 AE_STRING ('s', "string"),
429 AE_ENUM ('e', "enum"),
430 AE_CLASS ('c', "class"),
431 AE_ANNOTATION ('@', "annotation"),
432 AE_ARRAY ('[', "array"),
433 AE_UNKNOWN ((char)0, "unknown");
434
435 private char value;
436 private final String printval;
437
438 AnnotElemType(char val, String print) {
439 value = val;
440 printval = print;
441 }
442
443 public char val() {
444 return value;
445 }
446
447 public String printval() {
448 return printval;
449 }
450 }
451
452 private static void registerAnnotElemType(AnnotElemType typ) {
453 NameToAnnotElemType.put(typ.printval, typ);
454 AnnotElemTypes.put(typ.value, typ);
455 }
456
457 public static AnnotElemType annotElemType(String idValue) {
458 return NameToAnnotElemType.get(idValue);
459 }
460
461 public static AnnotElemType annotElemType(char subtag) {
462 AnnotElemType type = AnnotElemTypes.get(subtag);
463 if ( type == null ) {
464 type = AnnotElemType.AE_UNKNOWN;
465 }
466 return type;
467 }
468
469 public static String annotElemTypeName(char subtag) {
470 String retval = null;
471 AnnotElemType tg = AnnotElemTypes.get(subtag);
472 if (tg != null) {
473 retval = tg.printval;
474 }
475 return retval;
476 }
477
478 public static char annotElemTypeVal(String idValue) {
479 char retval = 0;
480 AnnotElemType tg = NameToAnnotElemType.get(idValue);
481 if (tg != null) {
482 retval = tg.value;
483 }
484 return retval;
485 }
486
487
488 /*-------------------------------------------------------- */
489 /**
490 * MapTypes table. These constants are used in stackmap pseudo-instructions only.
491 */
492 static public enum StackMapType {
493 /* Type codes for StackMap attribute */
494 ITEM_Bogus (0, "bogus", "B"), // an unknown or uninitialized value
495 ITEM_Integer (1, "int", "I"), // a 32-bit integer
496 ITEM_Float (2, "float", "F"), // not used
497 ITEM_Double (3, "double", "D"), // not used
498 ITEM_Long (4, "long", "L"), // a 64-bit integer
499 ITEM_Null (5, "null", "N"), // the type of null
500 ITEM_InitObject (6, "this", "IO"), // "this" in constructor
501 ITEM_Object (7, "CP", "O"), // followed by 2-byte index of class name
502 ITEM_NewObject (8, "at", "NO"), // followed by 2-byte ref to "new"
503 ITEM_UNKNOWN (null, "UNKNOWN", "UNKNOWN"); // placeholder for wrong types
504
505 private Integer value;
506 private final String printval;
507 private final String parsekey;
508
509 StackMapType(Integer val, String print, String parse) {
510 value = val;
511 printval = print;
512 parsekey = parse;
513 }
514
515 public String parsekey() {
516 return parsekey;
517 }
518
519 public String printval() {
520 return printval;
521 }
522
523 public Integer value() {
524 return value;
525 }
526 }
527
528 private static void registerStackMapType(StackMapType typ) {
529 KeyToStackMapType.put(typ.parsekey, typ);
530 NameToStackMapType.put(typ.printval, typ);
531 StackMapTypes.put(typ.value, typ);
532 }
533
534 public static StackMapType stackMapType(int subtag, PrintWriter out) {
535 StackMapType type = StackMapTypes.get(subtag);
536 if (type == null || type == StackMapType.ITEM_UNKNOWN) {
537 if (out != null)
538 out.println("// Unknown StackMap type " + subtag);
539 type = StackMapType.ITEM_UNKNOWN;
540 type.value = subtag;
541 }
542 return type;
543 }
544
545 public static StackMapType stackMapType(String subtag) {
546 return NameToStackMapType.get(subtag);
547 }
548
549 public static StackMapType stackMapTypeKey(String subtag) {
550 return KeyToStackMapType.get(subtag);
551 }
552
553 public static String stackMapTypeName(int subtag) {
554 String retval = null;
555 StackMapType tg = StackMapTypes.get(subtag);
556 if (tg != null) {
557 retval = tg.printval;
558 }
559 return retval;
560 }
561
562 public static int stackMapTypeValue(String idValue) {
563 int retval = 0;
564 StackMapType tg = NameToStackMapType.get(idValue);
565 if (tg != null) {
566 retval = tg.value;
567 }
568 return retval;
569 }
570
571
572 /*-------------------------------------------------------- */
573 /**
574 * StackMap-FrameType table. These constants are used in stackmap pseudo-instructions
575 * only.
576 */
577 static public enum StackMapFrameType {
578 /* Type codes for StackMapFrame attribute */
579 SAME_FRAME (0, "same"),
580 SAME_LOCALS_1_STACK_ITEM_FRAME (64, "stack1"),
581 SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME (247, "stack1_ex"),
582 CHOP_1_FRAME (250, "chop1"),
583 CHOP_2_FRAME (249, "chop2"),
584 CHOP_3_FRAME (248, "chop3"),
585 SAME_FRAME_EX (251, "same_ex"),
586 APPEND_FRAME (252, "append"),
587 FULL_FRAME (255, "full");
588
589 private final Integer value;
590 private final String parsekey;
591
592 StackMapFrameType(Integer val, String print) {
593 value = val;
594 parsekey = print;
595 }
596
597 public String parsekey() {
598 return parsekey;
599 }
600
601 public Integer value() {
602 return value;
603 }
604 }
605
606 private static void registerStackMapFrameType(StackMapFrameType typ) {
607 NameToStackMapFrameType.put(typ.parsekey, typ);
608 StackMapFrameTypes.put(typ.value, typ);
609 }
610
611 public static StackMapFrameType stackMapFrameTypeVal(int subtag) {
612 return StackMapFrameTypes.get(subtag);
613 }
614
615 public static String stackMapFrameTypeName(int subtag) {
616 String retval = null;
617 StackMapFrameType tg = StackMapFrameTypes.get(subtag);
618 if (tg != null) {
619 retval = tg.parsekey;
620 }
621 return retval;
622 }
623
624 public static StackMapFrameType stackMapFrameType(int subtag) {
625 StackMapFrameType frametype;
626 if (subtag < StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME.value()) {
627 // type is same_frame;
628 frametype = StackMapFrameType.SAME_FRAME;
629 } else if (subtag >= StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME.value()
630 && subtag <= 127) {
631 // type is same_locals_1_stack_item_frame
632 frametype = StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME;
633
634 } else if (subtag >= StackMapFrameType.APPEND_FRAME.value()
635 && subtag < StackMapFrameType.FULL_FRAME.value()) {
636 // type is append_frame
637 frametype = StackMapFrameType.APPEND_FRAME;
638 } else {
639 frametype = StackMapFrameTypes.get(subtag);
640 }
641 return frametype;
642 }
643
644 public static int stackMapFrameTypeValue(String idValue) {
645 int retval = 0;
646 StackMapFrameType tg = NameToStackMapFrameType.get(idValue);
647 if (tg != null) {
648 retval = tg.value;
649 }
650 return retval;
651 }
652
653 /**
654 * CF_Context enums
655 */
656 public enum CF_Context {
657
658 CTX_CLASS (0, "class"),
659 CTX_FIELD (1, "field"),
660 CTX_METHOD (2, "method"),
661 CTX_INNERCLASS (3, "inner-class"),
662 CTX_MODULE (4, "module") ;
663
664 private final int value;
665 private final String printval;
666
667 CF_Context(int val, String print) {
668 value = val;
669 printval = print;
670 }
671
672 boolean isOneOf(CF_Context... items) {
673 for(CF_Context item : items) {
674 if(item.value == value) {
675 return true;
676 }
677 }
678 return false;
679 }
680
681 public int val() {
682 return value;
683 }
684
685 public String printval() {
686 return printval;
687 }
688 }
689 }