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 }