+}
+
+void
+_Jv_ClassReader::finish_reflection_data ()
+{
+ if (data_stream == NULL)
+ return;
+ data_stream->writeByte(JV_DONE_ATTR);
+ data_stream->flush();
+ int nbytes = reflection_data->count;
+ unsigned char *new_bytes = (unsigned char *) _Jv_AllocBytes (nbytes);
+ memcpy (new_bytes, elements (reflection_data->buf), nbytes);
+ def->reflection_data = new_bytes;
+}
+
+void
+_Jv_ClassReader::handleEnclosingMethod (int len)
+{
+ if (len != 4)
+ throw_class_format_error ("invalid EnclosingMethod attribute");
+ // FIXME: only allow one...
+
+ int class_index = read2u();
+ check_tag (class_index, JV_CONSTANT_Class);
+ prepare_pool_entry (class_index, JV_CONSTANT_Class);
+
+ int method_index = read2u();
+ // Zero is ok and means no enclosing method.
+ if (method_index != 0)
+ {
+ check_tag (method_index, JV_CONSTANT_NameAndType);
+ prepare_pool_entry (method_index, JV_CONSTANT_NameAndType);
+ }
+
+ ::java::io::DataOutputStream *stream = get_reflection_stream ();
+ stream->writeByte(JV_CLASS_ATTR);
+ stream->writeInt(5);
+ stream->writeByte(JV_ENCLOSING_METHOD_KIND);
+ stream->writeShort(class_index);
+ stream->writeShort(method_index);
+}
+
+void
+_Jv_ClassReader::handleGenericSignature (jv_attr_type type,
+ unsigned short index,
+ int len)
+{
+ if (len != 2)
+ throw_class_format_error ("invalid Signature attribute");
+
+ int cpool_idx = read2u();
+ check_tag (cpool_idx, JV_CONSTANT_Utf8);
+ prepare_pool_entry (cpool_idx, JV_CONSTANT_Utf8, false);
+
+ ::java::io::DataOutputStream *stream = get_reflection_stream ();
+ stream->writeByte(type);
+ int attrlen = 3;
+ if (type != JV_CLASS_ATTR)
+ attrlen += 2;
+ stream->writeInt(attrlen);
+ if (type != JV_CLASS_ATTR)
+ stream->writeShort(index);
+ stream->writeByte(JV_SIGNATURE_KIND);
+ stream->writeShort(cpool_idx);
+}
+
+void
+_Jv_ClassReader::handleAnnotationElement()
+{
+ int tag = read1u();
+ switch (tag)
+ {
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ case 'I':
+ {
+ int index = read2u();
+ check_tag (index, JV_CONSTANT_Integer);
+ prepare_pool_entry (index, JV_CONSTANT_Integer);
+ }
+ break;
+ case 'D':
+ {
+ int index = read2u();
+ check_tag (index, JV_CONSTANT_Double);
+ prepare_pool_entry (index, JV_CONSTANT_Double);
+ }
+ break;
+ case 'F':
+ {
+ int index = read2u();
+ check_tag (index, JV_CONSTANT_Float);
+ prepare_pool_entry (index, JV_CONSTANT_Float);
+ }
+ break;
+ case 'J':
+ {
+ int index = read2u();
+ check_tag (index, JV_CONSTANT_Long);
+ prepare_pool_entry (index, JV_CONSTANT_Long);
+ }
+ break;
+ case 's':
+ {
+ int index = read2u();
+ // Despite what the JVM spec says, compilers generate a Utf8
+ // constant here, not a String.
+ check_tag (index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (index, JV_CONSTANT_Utf8, false);
+ }
+ break;
+
+ case 'e':
+ {
+ int type_name_index = read2u();
+ int const_name_index = read2u ();
+ check_tag (type_name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (type_name_index, JV_CONSTANT_Utf8);
+ check_tag (const_name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (const_name_index, JV_CONSTANT_Utf8, false);
+ }
+ break;
+ case 'c':
+ {
+ int index = read2u();
+ check_tag (index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (index, JV_CONSTANT_Utf8);
+ }
+ break;
+ case '@':
+ handleAnnotation();
+ break;
+ case '[':
+ {
+ int n_array_elts = read2u ();
+ for (int i = 0; i < n_array_elts; ++i)
+ handleAnnotationElement();
+ }
+ break;
+ default:
+ throw_class_format_error ("invalid annotation element");
+ }
+}
+
+void
+_Jv_ClassReader::handleAnnotation()
+{
+ int type_index = read2u();
+ check_tag (type_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
+
+ int npairs = read2u();
+ for (int i = 0; i < npairs; ++i)
+ {
+ int name_index = read2u();
+ check_tag (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name_index, JV_CONSTANT_Utf8, false);
+ handleAnnotationElement();
+ }
+}
+
+void
+_Jv_ClassReader::handleAnnotations()
+{
+ int num = read2u();
+ while (num--)
+ handleAnnotation();
+}
+
+void
+_Jv_ClassReader::handleMemberAnnotations(jv_attr_type member_type,
+ int member_index,
+ int len)
+{
+ // We're going to copy the bytes in verbatim. But first we want to
+ // make sure the attribute is well-formed, and we want to prepare
+ // the constant pool. So, we save our starting point.
+ int orig_pos = pos;
+
+ handleAnnotations();
+ // FIXME: check that we read all LEN bytes?
+
+ ::java::io::DataOutputStream *stream = get_reflection_stream ();
+ stream->writeByte(member_type);
+ int newLen = len + 1;
+ if (member_type != JV_CLASS_ATTR)
+ newLen += 2;
+ stream->writeInt(newLen);
+ stream->writeByte(JV_ANNOTATIONS_KIND);
+ if (member_type != JV_CLASS_ATTR)
+ stream->writeShort(member_index);
+ // Write the data as-is.
+ stream->write(input_data, input_offset + orig_pos, len);
+}
+
+void
+_Jv_ClassReader::handleAnnotationDefault(int member_index, int len)
+{
+ int orig_pos = pos;
+ handleAnnotationElement();
+
+ ::java::io::DataOutputStream *stream = get_reflection_stream ();
+ stream->writeByte(JV_METHOD_ATTR);
+ stream->writeInt(len + 3);
+ stream->writeByte(JV_ANNOTATION_DEFAULT_KIND);
+ stream->writeShort(member_index);
+ stream->write(input_data, input_offset + orig_pos, len);
+}