NOISSUE tabs -> spaces

This commit is contained in:
Petr Mrázek
2018-07-15 14:51:05 +02:00
parent 03280cc62e
commit bbb3b3e6f6
577 changed files with 51938 additions and 51938 deletions

View File

@ -47,188 +47,188 @@
void band::readData(int expectedLength)
{
assert(expectedLength >= 0);
assert(vs[0].cmk == cmk_ERROR);
if (expectedLength != 0)
{
assert(length == 0);
length = expectedLength;
}
if (length == 0)
{
assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
return;
}
assert(length > 0);
assert(expectedLength >= 0);
assert(vs[0].cmk == cmk_ERROR);
if (expectedLength != 0)
{
assert(length == 0);
length = expectedLength;
}
if (length == 0)
{
assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
return;
}
assert(length > 0);
bool is_BYTE1 = (defc->spec == BYTE1_spec);
bool is_BYTE1 = (defc->spec == BYTE1_spec);
if (is_BYTE1)
{
// No possibility of coding change. Sizing is exact.
u->ensure_input(length);
}
else
{
// Make a conservatively generous estimate of band size in bytes.
// Assume B == 5 everywhere.
// Assume awkward pop with all {U} values (2*5 per value)
int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
u->ensure_input(generous);
}
if (is_BYTE1)
{
// No possibility of coding change. Sizing is exact.
u->ensure_input(length);
}
else
{
// Make a conservatively generous estimate of band size in bytes.
// Assume B == 5 everywhere.
// Assume awkward pop with all {U} values (2*5 per value)
int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
u->ensure_input(generous);
}
// Read one value to see what it might be.
int XB = _meta_default;
if (!is_BYTE1)
{
// must be a variable-length coding
assert(defc->B() > 1 && defc->L() > 0);
// Read one value to see what it might be.
int XB = _meta_default;
if (!is_BYTE1)
{
// must be a variable-length coding
assert(defc->B() > 1 && defc->L() > 0);
value_stream xvs;
coding *valc = defc;
if (valc->D() != 0)
{
valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
assert(!valc->isMalloc);
}
xvs.init(u->rp, u->rplimit, valc);
int X = xvs.getInt();
if (valc->S() != 0)
{
assert(valc->min <= -256);
XB = -1 - X;
}
else
{
int L = valc->L();
assert(valc->max >= L + 255);
XB = X - L;
}
if (0 <= XB && XB < 256)
{
// Skip over the escape value.
u->rp = xvs.rp;
}
else
{
// No, it's still default.
XB = _meta_default;
}
}
value_stream xvs;
coding *valc = defc;
if (valc->D() != 0)
{
valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
assert(!valc->isMalloc);
}
xvs.init(u->rp, u->rplimit, valc);
int X = xvs.getInt();
if (valc->S() != 0)
{
assert(valc->min <= -256);
XB = -1 - X;
}
else
{
int L = valc->L();
assert(valc->max >= L + 255);
XB = X - L;
}
if (0 <= XB && XB < 256)
{
// Skip over the escape value.
u->rp = xvs.rp;
}
else
{
// No, it's still default.
XB = _meta_default;
}
}
if (XB <= _meta_canon_max)
{
byte XB_byte = (byte)XB;
byte *XB_ptr = &XB_byte;
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
}
else
{
assert(u->meta_rp != nullptr);
// Scribble the initial byte onto the band.
byte *save_meta_rp = --u->meta_rp;
byte save_meta_xb = (*save_meta_rp);
(*save_meta_rp) = (byte)XB;
cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
(*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
}
rplimit = u->rp;
if (XB <= _meta_canon_max)
{
byte XB_byte = (byte)XB;
byte *XB_ptr = &XB_byte;
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
}
else
{
assert(u->meta_rp != nullptr);
// Scribble the initial byte onto the band.
byte *save_meta_rp = --u->meta_rp;
byte save_meta_xb = (*save_meta_rp);
(*save_meta_rp) = (byte)XB;
cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
(*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
}
rplimit = u->rp;
rewind();
rewind();
}
void band::setIndex(cpindex *ix_)
{
assert(ix_ == nullptr || ixTag == ix_->ixTag);
ix = ix_;
assert(ix_ == nullptr || ixTag == ix_->ixTag);
ix = ix_;
}
void band::setIndexByTag(byte tag)
{
setIndex(u->cp.getIndex(tag));
setIndex(u->cp.getIndex(tag));
}
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
{
assert(ix_->ixTag == ixTag ||
(ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
ix_->ixTag <= CONSTANT_String));
int n = vs[0].getInt() - nullOK;
// Note: band-local nullOK means nullptr encodes as 0.
// But nullOKwithCaller means caller is willing to tolerate a nullptr.
entry *ref = ix_->get(n);
if (ref == nullptr && !(nullOKwithCaller && n == -1))
unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
return ref;
assert(ix_->ixTag == ixTag ||
(ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
ix_->ixTag <= CONSTANT_String));
int n = vs[0].getInt() - nullOK;
// Note: band-local nullOK means nullptr encodes as 0.
// But nullOKwithCaller means caller is willing to tolerate a nullptr.
entry *ref = ix_->get(n);
if (ref == nullptr && !(nullOKwithCaller && n == -1))
unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
return ref;
}
int64_t band::getLong(band &lo_band, bool have_hi)
{
band &hi_band = (*this);
assert(lo_band.bn == hi_band.bn + 1);
uint32_t lo = lo_band.getInt();
if (!have_hi)
{
assert(hi_band.length == 0);
return makeLong(0, lo);
}
uint32_t hi = hi_band.getInt();
return makeLong(hi, lo);
band &hi_band = (*this);
assert(lo_band.bn == hi_band.bn + 1);
uint32_t lo = lo_band.getInt();
if (!have_hi)
{
assert(hi_band.length == 0);
return makeLong(0, lo);
}
uint32_t hi = hi_band.getInt();
return makeLong(hi, lo);
}
int band::getIntTotal()
{
if (length == 0)
return 0;
if (total_memo > 0)
return total_memo - 1;
int total = getInt();
// overflow checks require that none of the addends are <0,
// and that the partial sums never overflow (wrap negative)
if (total < 0)
{
unpack_abort("overflow detected");
}
for (int k = length - 1; k > 0; k--)
{
int prev_total = total;
total += vs[0].getInt();
if (total < prev_total)
{
unpack_abort("overflow detected");
}
}
rewind();
total_memo = total + 1;
return total;
if (length == 0)
return 0;
if (total_memo > 0)
return total_memo - 1;
int total = getInt();
// overflow checks require that none of the addends are <0,
// and that the partial sums never overflow (wrap negative)
if (total < 0)
{
unpack_abort("overflow detected");
}
for (int k = length - 1; k > 0; k--)
{
int prev_total = total;
total += vs[0].getInt();
if (total < prev_total)
{
unpack_abort("overflow detected");
}
}
rewind();
total_memo = total + 1;
return total;
}
int band::getIntCount(int tag)
{
if (length == 0)
return 0;
if (tag >= HIST0_MIN && tag <= HIST0_MAX)
{
if (hist0 == nullptr)
{
// Lazily calculate an approximate histogram.
hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
for (int k = length; k > 0; k--)
{
int x = vs[0].getInt();
if (x >= HIST0_MIN && x <= HIST0_MAX)
hist0[x - HIST0_MIN] += 1;
}
rewind();
}
return hist0[tag - HIST0_MIN];
}
int total = 0;
for (int k = length; k > 0; k--)
{
total += (vs[0].getInt() == tag) ? 1 : 0;
}
rewind();
return total;
if (length == 0)
return 0;
if (tag >= HIST0_MIN && tag <= HIST0_MAX)
{
if (hist0 == nullptr)
{
// Lazily calculate an approximate histogram.
hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
for (int k = length; k > 0; k--)
{
int x = vs[0].getInt();
if (x >= HIST0_MIN && x <= HIST0_MAX)
hist0[x - HIST0_MIN] += 1;
}
rewind();
}
return hist0[tag - HIST0_MIN];
}
int total = 0;
for (int k = length; k > 0; k--)
{
total += (vs[0].getInt() == tag) ? 1 : 0;
}
rewind();
return total;
}
#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
@ -240,184 +240,184 @@ int band::getIntCount(int tag)
struct band_init
{
int defc;
int index;
int defc;
int index;
};
#define BAND_INIT(name, cspec, ix) \
{ \
cspec, ix \
}
{ \
cspec, ix \
}
const band_init all_band_inits[] =
{
// BAND_INIT(archive_magic, BYTE1_spec, 0),
// BAND_INIT(archive_header, UNSIGNED5_spec, 0),
// BAND_INIT(band_headers, BYTE1_spec, 0),
BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_interface_count, DELTA5_spec, 0),
BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_field_count, DELTA5_spec, 0),
BAND_INIT(class_method_count, DELTA5_spec, 0),
BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
NULL_OR_INDEX(CONSTANT_NameandType)),
BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(class_metadata_bands, -1, -1),
BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
BAND_INIT(code_handler_start_P, BCI5_spec, 0),
BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
INDEX(CONSTANT_Signature)),
BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
BAND_INIT(bc_escbyte, BYTE1_spec, 0),
BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
// BAND_INIT(file_bits, BYTE1_spec, 0),
{0, 0}};
{
// BAND_INIT(archive_magic, BYTE1_spec, 0),
// BAND_INIT(archive_header, UNSIGNED5_spec, 0),
// BAND_INIT(band_headers, BYTE1_spec, 0),
BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_interface_count, DELTA5_spec, 0),
BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_field_count, DELTA5_spec, 0),
BAND_INIT(class_method_count, DELTA5_spec, 0),
BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
NULL_OR_INDEX(CONSTANT_NameandType)),
BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(class_metadata_bands, -1, -1),
BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
BAND_INIT(code_handler_start_P, BCI5_spec, 0),
BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
INDEX(CONSTANT_Signature)),
BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
BAND_INIT(bc_escbyte, BYTE1_spec, 0),
BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
// BAND_INIT(file_bits, BYTE1_spec, 0),
{0, 0}};
band *band::makeBands(unpacker *u)
{
band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
for (int i = 0; i < BAND_LIMIT; i++)
{
assert((byte *)&all_band_inits[i + 1] <
(byte *)all_band_inits + sizeof(all_band_inits));
const band_init &bi = all_band_inits[i];
band &b = tmp_all_bands[i];
coding *defc = coding::findBySpec(bi.defc);
assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
assert(defc == nullptr || !defc->isMalloc);
b.init(u, i, defc);
if (bi.index > 0)
{
b.nullOK = ((bi.index >> 8) & 1);
b.ixTag = (bi.index & 0xFF);
}
}
return tmp_all_bands;
band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
for (int i = 0; i < BAND_LIMIT; i++)
{
assert((byte *)&all_band_inits[i + 1] <
(byte *)all_band_inits + sizeof(all_band_inits));
const band_init &bi = all_band_inits[i];
band &b = tmp_all_bands[i];
coding *defc = coding::findBySpec(bi.defc);
assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
assert(defc == nullptr || !defc->isMalloc);
b.init(u, i, defc);
if (bi.index > 0)
{
b.nullOK = ((bi.index >> 8) & 1);
b.ixTag = (bi.index & 0xFF);
}
}
return tmp_all_bands;
}
void band::initIndexes(unpacker *u)
{
band *tmp_all_bands = u->all_bands;
for (int i = 0; i < BAND_LIMIT; i++)
{
band *scan = &tmp_all_bands[i];
uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
{
scan->setIndex(u->cp.getIndex(tag));
}
}
band *tmp_all_bands = u->all_bands;
for (int i = 0; i < BAND_LIMIT; i++)
{
band *scan = &tmp_all_bands[i];
uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
{
scan->setIndex(u->cp.getIndex(tag));
}
}
}

View File

@ -30,138 +30,138 @@ struct unpacker;
struct band
{
int bn; // band_number of this band
coding *defc; // default coding method
cpindex *ix; // CP entry mapping, if CPRefBand
byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
int length; // expected # values
unpacker *u; // back pointer
int bn; // band_number of this band
coding *defc; // default coding method
cpindex *ix; // CP entry mapping, if CPRefBand
byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
int length; // expected # values
unpacker *u; // back pointer
value_stream vs[2]; // source of values
coding_method cm; // method used for initial state of vs[0]
byte *rplimit; // end of band (encoded, transmitted)
value_stream vs[2]; // source of values
coding_method cm; // method used for initial state of vs[0]
byte *rplimit; // end of band (encoded, transmitted)
int total_memo; // cached value of getIntTotal, or -1
int *hist0; // approximate. histogram
enum
{
HIST0_MIN = 0,
HIST0_MAX = 255
}; // catches the usual cases
int total_memo; // cached value of getIntTotal, or -1
int *hist0; // approximate. histogram
enum
{
HIST0_MIN = 0,
HIST0_MAX = 255
}; // catches the usual cases
// properties for attribute layout elements:
byte le_kind; // EK_XXX
byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
byte le_back; // ==EF_BACK
byte le_len; // 0,1,2,4 (size in classfile), or call addr
band **le_body; // body of repl, union, call (nullptr-terminated)
// properties for attribute layout elements:
byte le_kind; // EK_XXX
byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
byte le_back; // ==EF_BACK
byte le_len; // 0,1,2,4 (size in classfile), or call addr
band **le_body; // body of repl, union, call (nullptr-terminated)
// Note: EK_CASE elements use hist0 to record union tags.
#define le_casetags hist0
band &nextBand()
{
return this[1];
}
band &prevBand()
{
return this[-1];
}
band &nextBand()
{
return this[1];
}
band &prevBand()
{
return this[-1];
}
void init(unpacker *u_, int bn_, coding *defc_)
{
u = u_;
cm.u = u_;
bn = bn_;
defc = defc_;
}
void init(unpacker *u_, int bn_, int defcSpec)
{
init(u_, bn_, coding::findBySpec(defcSpec));
}
void initRef(int ixTag_ = 0, bool nullOK_ = false)
{
ixTag = ixTag_;
nullOK = nullOK_;
setIndexByTag(ixTag);
}
void init(unpacker *u_, int bn_, coding *defc_)
{
u = u_;
cm.u = u_;
bn = bn_;
defc = defc_;
}
void init(unpacker *u_, int bn_, int defcSpec)
{
init(u_, bn_, coding::findBySpec(defcSpec));
}
void initRef(int ixTag_ = 0, bool nullOK_ = false)
{
ixTag = ixTag_;
nullOK = nullOK_;
setIndexByTag(ixTag);
}
void expectMoreLength(int l)
{
assert(length >= 0); // able to accept a length
assert((int)l >= 0); // no overflow
assert(rplimit == nullptr); // readData not yet called
length += l;
assert(length >= l); // no overflow
}
void expectMoreLength(int l)
{
assert(length >= 0); // able to accept a length
assert((int)l >= 0); // no overflow
assert(rplimit == nullptr); // readData not yet called
length += l;
assert(length >= l); // no overflow
}
void setIndex(cpindex *ix_);
void setIndexByTag(byte tag);
void setIndex(cpindex *ix_);
void setIndexByTag(byte tag);
// Parse the band and its meta-coding header.
void readData(int expectedLength = 0);
// Parse the band and its meta-coding header.
void readData(int expectedLength = 0);
// Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
void rewind()
{
cm.reset(&vs[0]);
}
// Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
void rewind()
{
cm.reset(&vs[0]);
}
byte *&curRP()
{
return vs[0].rp;
}
byte *minRP()
{
return cm.vs0.rp;
}
byte *maxRP()
{
return rplimit;
}
size_t size()
{
return maxRP() - minRP();
}
byte *&curRP()
{
return vs[0].rp;
}
byte *minRP()
{
return cm.vs0.rp;
}
byte *maxRP()
{
return rplimit;
}
size_t size()
{
return maxRP() - minRP();
}
int getByte()
{
assert(ix == nullptr);
return vs[0].getByte();
}
int getInt()
{
assert(ix == nullptr);
return vs[0].getInt();
}
entry *getRefN()
{
assert(ix != nullptr);
return getRefCommon(ix, true);
}
entry *getRef()
{
assert(ix != nullptr);
return getRefCommon(ix, false);
}
entry *getRefUsing(cpindex *ix2)
{
assert(ix == nullptr);
return getRefCommon(ix2, true);
}
entry *getRefCommon(cpindex *ix, bool nullOK);
int64_t getLong(band &lo_band, bool have_hi);
int getByte()
{
assert(ix == nullptr);
return vs[0].getByte();
}
int getInt()
{
assert(ix == nullptr);
return vs[0].getInt();
}
entry *getRefN()
{
assert(ix != nullptr);
return getRefCommon(ix, true);
}
entry *getRef()
{
assert(ix != nullptr);
return getRefCommon(ix, false);
}
entry *getRefUsing(cpindex *ix2)
{
assert(ix == nullptr);
return getRefCommon(ix2, true);
}
entry *getRefCommon(cpindex *ix, bool nullOK);
int64_t getLong(band &lo_band, bool have_hi);
static int64_t makeLong(uint32_t hi, uint32_t lo)
{
return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
}
static int64_t makeLong(uint32_t hi, uint32_t lo)
{
return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
}
int getIntTotal();
int getIntCount(int tag);
int getIntTotal();
int getIntCount(int tag);
static band *makeBands(unpacker *u);
static void initIndexes(unpacker *u);
static band *makeBands(unpacker *u);
static void initIndexes(unpacker *u);
};
extern band all_bands[];
@ -173,179 +173,179 @@ extern band all_bands[];
// Band schema:
enum band_number
{
// e_archive_magic,
// e_archive_header,
// e_band_headers,
// e_archive_magic,
// e_archive_header,
// e_band_headers,
// constant pool contents
e_cp_Utf8_prefix,
e_cp_Utf8_suffix,
e_cp_Utf8_chars,
e_cp_Utf8_big_suffix,
e_cp_Utf8_big_chars,
e_cp_Int,
e_cp_Float,
e_cp_Long_hi,
e_cp_Long_lo,
e_cp_Double_hi,
e_cp_Double_lo,
e_cp_String,
e_cp_Class,
e_cp_Signature_form,
e_cp_Signature_classes,
e_cp_Descr_name,
e_cp_Descr_type,
e_cp_Field_class,
e_cp_Field_desc,
e_cp_Method_class,
e_cp_Method_desc,
e_cp_Imethod_class,
e_cp_Imethod_desc,
// constant pool contents
e_cp_Utf8_prefix,
e_cp_Utf8_suffix,
e_cp_Utf8_chars,
e_cp_Utf8_big_suffix,
e_cp_Utf8_big_chars,
e_cp_Int,
e_cp_Float,
e_cp_Long_hi,
e_cp_Long_lo,
e_cp_Double_hi,
e_cp_Double_lo,
e_cp_String,
e_cp_Class,
e_cp_Signature_form,
e_cp_Signature_classes,
e_cp_Descr_name,
e_cp_Descr_type,
e_cp_Field_class,
e_cp_Field_desc,
e_cp_Method_class,
e_cp_Method_desc,
e_cp_Imethod_class,
e_cp_Imethod_desc,
// bands which define transmission of attributes
e_attr_definition_headers,
e_attr_definition_name,
e_attr_definition_layout,
// bands which define transmission of attributes
e_attr_definition_headers,
e_attr_definition_name,
e_attr_definition_layout,
// band for hardwired InnerClasses attribute (shared across the package)
e_ic_this_class,
e_ic_flags,
// These bands contain data only where flags sets ACC_IC_LONG_FORM:
e_ic_outer_class,
e_ic_name,
// band for hardwired InnerClasses attribute (shared across the package)
e_ic_this_class,
e_ic_flags,
// These bands contain data only where flags sets ACC_IC_LONG_FORM:
e_ic_outer_class,
e_ic_name,
// bands for carrying class schema information:
e_class_this,
e_class_super,
e_class_interface_count,
e_class_interface,
// bands for carrying class schema information:
e_class_this,
e_class_super,
e_class_interface_count,
e_class_interface,
// bands for class members
e_class_field_count,
e_class_method_count,
e_field_descr,
e_field_flags_hi,
e_field_flags_lo,
e_field_attr_count,
e_field_attr_indexes,
e_field_attr_calls,
e_field_ConstantValue_KQ,
e_field_Signature_RS,
e_field_metadata_bands,
e_field_attr_bands,
e_method_descr,
e_method_flags_hi,
e_method_flags_lo,
e_method_attr_count,
e_method_attr_indexes,
e_method_attr_calls,
e_method_Exceptions_N,
e_method_Exceptions_RC,
e_method_Signature_RS,
e_method_metadata_bands,
e_method_attr_bands,
e_class_flags_hi,
e_class_flags_lo,
e_class_attr_count,
e_class_attr_indexes,
e_class_attr_calls,
e_class_SourceFile_RUN,
e_class_EnclosingMethod_RC,
e_class_EnclosingMethod_RDN,
e_class_Signature_RS,
e_class_metadata_bands,
e_class_InnerClasses_N,
e_class_InnerClasses_RC,
e_class_InnerClasses_F,
e_class_InnerClasses_outer_RCN,
e_class_InnerClasses_name_RUN,
e_class_ClassFile_version_minor_H,
e_class_ClassFile_version_major_H,
e_class_attr_bands,
e_code_headers,
e_code_max_stack,
e_code_max_na_locals,
e_code_handler_count,
e_code_handler_start_P,
e_code_handler_end_PO,
e_code_handler_catch_PO,
e_code_handler_class_RCN,
// bands for class members
e_class_field_count,
e_class_method_count,
e_field_descr,
e_field_flags_hi,
e_field_flags_lo,
e_field_attr_count,
e_field_attr_indexes,
e_field_attr_calls,
e_field_ConstantValue_KQ,
e_field_Signature_RS,
e_field_metadata_bands,
e_field_attr_bands,
e_method_descr,
e_method_flags_hi,
e_method_flags_lo,
e_method_attr_count,
e_method_attr_indexes,
e_method_attr_calls,
e_method_Exceptions_N,
e_method_Exceptions_RC,
e_method_Signature_RS,
e_method_metadata_bands,
e_method_attr_bands,
e_class_flags_hi,
e_class_flags_lo,
e_class_attr_count,
e_class_attr_indexes,
e_class_attr_calls,
e_class_SourceFile_RUN,
e_class_EnclosingMethod_RC,
e_class_EnclosingMethod_RDN,
e_class_Signature_RS,
e_class_metadata_bands,
e_class_InnerClasses_N,
e_class_InnerClasses_RC,
e_class_InnerClasses_F,
e_class_InnerClasses_outer_RCN,
e_class_InnerClasses_name_RUN,
e_class_ClassFile_version_minor_H,
e_class_ClassFile_version_major_H,
e_class_attr_bands,
e_code_headers,
e_code_max_stack,
e_code_max_na_locals,
e_code_handler_count,
e_code_handler_start_P,
e_code_handler_end_PO,
e_code_handler_catch_PO,
e_code_handler_class_RCN,
// code attributes
e_code_flags_hi,
e_code_flags_lo,
e_code_attr_count,
e_code_attr_indexes,
e_code_attr_calls,
e_code_StackMapTable_N,
e_code_StackMapTable_frame_T,
e_code_StackMapTable_local_N,
e_code_StackMapTable_stack_N,
e_code_StackMapTable_offset,
e_code_StackMapTable_T,
e_code_StackMapTable_RC,
e_code_StackMapTable_P,
e_code_LineNumberTable_N,
e_code_LineNumberTable_bci_P,
e_code_LineNumberTable_line,
e_code_LocalVariableTable_N,
e_code_LocalVariableTable_bci_P,
e_code_LocalVariableTable_span_O,
e_code_LocalVariableTable_name_RU,
e_code_LocalVariableTable_type_RS,
e_code_LocalVariableTable_slot,
e_code_LocalVariableTypeTable_N,
e_code_LocalVariableTypeTable_bci_P,
e_code_LocalVariableTypeTable_span_O,
e_code_LocalVariableTypeTable_name_RU,
e_code_LocalVariableTypeTable_type_RS,
e_code_LocalVariableTypeTable_slot,
e_code_attr_bands,
// code attributes
e_code_flags_hi,
e_code_flags_lo,
e_code_attr_count,
e_code_attr_indexes,
e_code_attr_calls,
e_code_StackMapTable_N,
e_code_StackMapTable_frame_T,
e_code_StackMapTable_local_N,
e_code_StackMapTable_stack_N,
e_code_StackMapTable_offset,
e_code_StackMapTable_T,
e_code_StackMapTable_RC,
e_code_StackMapTable_P,
e_code_LineNumberTable_N,
e_code_LineNumberTable_bci_P,
e_code_LineNumberTable_line,
e_code_LocalVariableTable_N,
e_code_LocalVariableTable_bci_P,
e_code_LocalVariableTable_span_O,
e_code_LocalVariableTable_name_RU,
e_code_LocalVariableTable_type_RS,
e_code_LocalVariableTable_slot,
e_code_LocalVariableTypeTable_N,
e_code_LocalVariableTypeTable_bci_P,
e_code_LocalVariableTypeTable_span_O,
e_code_LocalVariableTypeTable_name_RU,
e_code_LocalVariableTypeTable_type_RS,
e_code_LocalVariableTypeTable_slot,
e_code_attr_bands,
// bands for bytecodes
e_bc_codes,
// remaining bands provide typed opcode fields required by the bc_codes
e_bc_case_count,
e_bc_case_value,
e_bc_byte,
e_bc_short,
e_bc_local,
e_bc_label,
// bands for bytecodes
e_bc_codes,
// remaining bands provide typed opcode fields required by the bc_codes
e_bc_case_count,
e_bc_case_value,
e_bc_byte,
e_bc_short,
e_bc_local,
e_bc_label,
// ldc* operands:
e_bc_intref,
e_bc_floatref,
e_bc_longref,
e_bc_doubleref,
e_bc_stringref,
e_bc_classref,
e_bc_fieldref,
e_bc_methodref,
e_bc_imethodref,
// ldc* operands:
e_bc_intref,
e_bc_floatref,
e_bc_longref,
e_bc_doubleref,
e_bc_stringref,
e_bc_classref,
e_bc_fieldref,
e_bc_methodref,
e_bc_imethodref,
// _self_linker_op family
e_bc_thisfield,
e_bc_superfield,
e_bc_thismethod,
e_bc_supermethod,
// _self_linker_op family
e_bc_thisfield,
e_bc_superfield,
e_bc_thismethod,
e_bc_supermethod,
// bc_invokeinit family:
e_bc_initref,
// bc_invokeinit family:
e_bc_initref,
// bytecode escape sequences
e_bc_escref,
e_bc_escrefsize,
e_bc_escsize,
e_bc_escbyte,
// bytecode escape sequences
e_bc_escref,
e_bc_escrefsize,
e_bc_escsize,
e_bc_escbyte,
// file attributes and contents
e_file_name,
e_file_size_hi,
e_file_size_lo,
e_file_modtime,
e_file_options,
// e_file_bits, // handled specially as an appendix
BAND_LIMIT
// file attributes and contents
e_file_name,
e_file_size_hi,
e_file_size_lo,
e_file_modtime,
e_file_options,
// e_file_bits, // handled specially as an appendix
BAND_LIMIT
};
// Symbolic names for bands, as if in a giant global struct:

View File

@ -36,182 +36,182 @@ static byte dummy[1 << 10];
bool bytes::inBounds(const void *p)
{
return p >= ptr && p < limit();
return p >= ptr && p < limit();
}
void bytes::malloc(size_t len_)
{
len = len_;
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
if (ptr == nullptr)
{
// set ptr to some victim memory, to ease escape
set(dummy, sizeof(dummy) - 1);
unpack_abort(ERROR_ENOMEM);
}
len = len_;
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
if (ptr == nullptr)
{
// set ptr to some victim memory, to ease escape
set(dummy, sizeof(dummy) - 1);
unpack_abort(ERROR_ENOMEM);
}
}
void bytes::realloc(size_t len_)
{
if (len == len_)
return; // nothing to do
if (ptr == dummy)
return; // escaping from an error
if (ptr == nullptr)
{
malloc(len_);
return;
}
byte *oldptr = ptr;
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
if (ptr != nullptr)
{
if (len < len_)
memset(ptr + len, 0, len_ - len);
ptr[len_] = 0;
len = len_;
}
else
{
ptr = oldptr; // ease our escape
unpack_abort(ERROR_ENOMEM);
}
if (len == len_)
return; // nothing to do
if (ptr == dummy)
return; // escaping from an error
if (ptr == nullptr)
{
malloc(len_);
return;
}
byte *oldptr = ptr;
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
if (ptr != nullptr)
{
if (len < len_)
memset(ptr + len, 0, len_ - len);
ptr[len_] = 0;
len = len_;
}
else
{
ptr = oldptr; // ease our escape
unpack_abort(ERROR_ENOMEM);
}
}
void bytes::free()
{
if (ptr == dummy)
return; // escaping from an error
if (ptr != nullptr)
{
::free(ptr);
}
len = 0;
ptr = 0;
if (ptr == dummy)
return; // escaping from an error
if (ptr != nullptr)
{
::free(ptr);
}
len = 0;
ptr = 0;
}
int bytes::indexOf(byte c)
{
byte *p = (byte *)memchr(ptr, c, len);
return (p == 0) ? -1 : (int)(p - ptr);
byte *p = (byte *)memchr(ptr, c, len);
return (p == 0) ? -1 : (int)(p - ptr);
}
byte *bytes::writeTo(byte *bp)
{
memcpy(bp, ptr, len);
return bp + len;
memcpy(bp, ptr, len);
return bp + len;
}
int bytes::compareTo(bytes &other)
{
size_t l1 = len;
size_t l2 = other.len;
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
if (cmp != 0)
return cmp;
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
size_t l1 = len;
size_t l2 = other.len;
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
if (cmp != 0)
return cmp;
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
}
void bytes::saveFrom(const void *ptr_, size_t len_)
{
malloc(len_);
// Save as much as possible.
if (len_ > len)
{
assert(ptr == dummy); // error recovery
len_ = len;
}
copyFrom(ptr_, len_);
malloc(len_);
// Save as much as possible.
if (len_ > len)
{
assert(ptr == dummy); // error recovery
len_ = len;
}
copyFrom(ptr_, len_);
}
//#TODO: Need to fix for exception handling
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
{
assert(len_ == 0 || inBounds(ptr + offset));
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
memcpy(ptr + offset, ptr_, len_);
assert(len_ == 0 || inBounds(ptr + offset));
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
memcpy(ptr + offset, ptr_, len_);
}
// Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer.
byte *fillbytes::grow(size_t s)
{
size_t nlen = add_size(b.len, s);
if (nlen <= allocated)
{
b.len = nlen;
return limit() - s;
}
size_t maxlen = nlen;
if (maxlen < 128)
maxlen = 128;
if (maxlen < allocated * 2)
maxlen = allocated * 2;
if (allocated == 0)
{
// Initial buffer was not malloced. Do not reallocate it.
bytes old = b;
b.malloc(maxlen);
if (b.len == maxlen)
old.writeTo(b.ptr);
}
else
{
b.realloc(maxlen);
}
allocated = b.len;
if (allocated != maxlen)
{
b.len = nlen - s; // back up
return dummy; // scribble during error recov.
}
// after realloc, recompute pointers
b.len = nlen;
assert(b.len <= allocated);
return limit() - s;
size_t nlen = add_size(b.len, s);
if (nlen <= allocated)
{
b.len = nlen;
return limit() - s;
}
size_t maxlen = nlen;
if (maxlen < 128)
maxlen = 128;
if (maxlen < allocated * 2)
maxlen = allocated * 2;
if (allocated == 0)
{
// Initial buffer was not malloced. Do not reallocate it.
bytes old = b;
b.malloc(maxlen);
if (b.len == maxlen)
old.writeTo(b.ptr);
}
else
{
b.realloc(maxlen);
}
allocated = b.len;
if (allocated != maxlen)
{
b.len = nlen - s; // back up
return dummy; // scribble during error recov.
}
// after realloc, recompute pointers
b.len = nlen;
assert(b.len <= allocated);
return limit() - s;
}
void fillbytes::ensureSize(size_t s)
{
if (allocated >= s)
return;
size_t len0 = b.len;
grow(s - size());
b.len = len0; // put it back
if (allocated >= s)
return;
size_t len0 = b.len;
grow(s - size());
b.len = len0; // put it back
}
int ptrlist::indexOf(const void *x)
{
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
}
void ptrlist::freeAll()
{
int len = length();
for (int i = 0; i < len; i++)
{
void *p = (void *)get(i);
if (p != nullptr)
{
::free(p);
}
}
free();
int len = length();
for (int i = 0; i < len; i++)
{
void *p = (void *)get(i);
if (p != nullptr)
{
::free(p);
}
}
free();
}
int intlist::indexOf(int x)
{
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
}

View File

@ -27,225 +27,225 @@
struct bytes
{
int8_t *ptr;
size_t len;
int8_t *limit()
{
return ptr + len;
}
int8_t *ptr;
size_t len;
int8_t *limit()
{
return ptr + len;
}
void set(int8_t *ptr_, size_t len_)
{
ptr = ptr_;
len = len_;
}
void set(const char *str)
{
ptr = (int8_t *)str;
len = strlen(str);
}
bool inBounds(const void *p); // p in [ptr, limit)
void malloc(size_t len_);
void realloc(size_t len_);
void free();
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
void saveFrom(const void *ptr_, size_t len_);
void saveFrom(const char *str)
{
saveFrom(str, strlen(str));
}
void copyFrom(bytes &other, size_t offset = 0)
{
copyFrom(other.ptr, other.len, offset);
}
void saveFrom(bytes &other)
{
saveFrom(other.ptr, other.len);
}
void clear(int fill_byte = 0)
{
memset(ptr, fill_byte, len);
}
int8_t *writeTo(int8_t *bp);
bool equals(bytes &other)
{
return 0 == compareTo(other);
}
int compareTo(bytes &other);
bool contains(int8_t c)
{
return indexOf(c) >= 0;
}
int indexOf(int8_t c);
// substrings:
static bytes of(int8_t *ptr, size_t len)
{
bytes res;
res.set(ptr, len);
return res;
}
bytes slice(size_t beg, size_t end)
{
bytes res;
res.ptr = ptr + beg;
res.len = end - beg;
assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
return res;
}
// building C strings inside byte buffers:
bytes &strcat(const char *str)
{
::strcat((char *)ptr, str);
return *this;
}
bytes &strcat(bytes &other)
{
::strncat((char *)ptr, (char *)other.ptr, other.len);
return *this;
}
char *strval()
{
assert(strlen((char *)ptr) == len);
return (char *)ptr;
}
void set(int8_t *ptr_, size_t len_)
{
ptr = ptr_;
len = len_;
}
void set(const char *str)
{
ptr = (int8_t *)str;
len = strlen(str);
}
bool inBounds(const void *p); // p in [ptr, limit)
void malloc(size_t len_);
void realloc(size_t len_);
void free();
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
void saveFrom(const void *ptr_, size_t len_);
void saveFrom(const char *str)
{
saveFrom(str, strlen(str));
}
void copyFrom(bytes &other, size_t offset = 0)
{
copyFrom(other.ptr, other.len, offset);
}
void saveFrom(bytes &other)
{
saveFrom(other.ptr, other.len);
}
void clear(int fill_byte = 0)
{
memset(ptr, fill_byte, len);
}
int8_t *writeTo(int8_t *bp);
bool equals(bytes &other)
{
return 0 == compareTo(other);
}
int compareTo(bytes &other);
bool contains(int8_t c)
{
return indexOf(c) >= 0;
}
int indexOf(int8_t c);
// substrings:
static bytes of(int8_t *ptr, size_t len)
{
bytes res;
res.set(ptr, len);
return res;
}
bytes slice(size_t beg, size_t end)
{
bytes res;
res.ptr = ptr + beg;
res.len = end - beg;
assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
return res;
}
// building C strings inside byte buffers:
bytes &strcat(const char *str)
{
::strcat((char *)ptr, str);
return *this;
}
bytes &strcat(bytes &other)
{
::strncat((char *)ptr, (char *)other.ptr, other.len);
return *this;
}
char *strval()
{
assert(strlen((char *)ptr) == len);
return (char *)ptr;
}
};
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
struct fillbytes
{
bytes b;
size_t allocated;
bytes b;
size_t allocated;
int8_t *base()
{
return b.ptr;
}
size_t size()
{
return b.len;
}
int8_t *limit()
{
return b.limit();
} // logical limit
void setLimit(int8_t *lp)
{
assert(isAllocated(lp));
b.len = lp - b.ptr;
}
int8_t *end()
{
return b.ptr + allocated;
} // physical limit
int8_t *loc(size_t o)
{
assert(o < b.len);
return b.ptr + o;
}
void init()
{
allocated = 0;
b.set(nullptr, 0);
}
void init(size_t s)
{
init();
ensureSize(s);
}
void free()
{
if (allocated != 0)
b.free();
allocated = 0;
}
void empty()
{
b.len = 0;
}
int8_t *grow(size_t s); // grow so that limit() += s
int getByte(uint32_t i)
{
return *loc(i) & 0xFF;
}
void addByte(int8_t x)
{
*grow(1) = x;
}
void ensureSize(size_t s); // make sure allocated >= s
void trimToSize()
{
if (allocated > size())
b.realloc(allocated = size());
}
bool canAppend(size_t s)
{
return allocated > b.len + s;
}
bool isAllocated(int8_t *p)
{
return p >= base() && p <= end();
} // asserts
void set(bytes &src)
{
set(src.ptr, src.len);
}
int8_t *base()
{
return b.ptr;
}
size_t size()
{
return b.len;
}
int8_t *limit()
{
return b.limit();
} // logical limit
void setLimit(int8_t *lp)
{
assert(isAllocated(lp));
b.len = lp - b.ptr;
}
int8_t *end()
{
return b.ptr + allocated;
} // physical limit
int8_t *loc(size_t o)
{
assert(o < b.len);
return b.ptr + o;
}
void init()
{
allocated = 0;
b.set(nullptr, 0);
}
void init(size_t s)
{
init();
ensureSize(s);
}
void free()
{
if (allocated != 0)
b.free();
allocated = 0;
}
void empty()
{
b.len = 0;
}
int8_t *grow(size_t s); // grow so that limit() += s
int getByte(uint32_t i)
{
return *loc(i) & 0xFF;
}
void addByte(int8_t x)
{
*grow(1) = x;
}
void ensureSize(size_t s); // make sure allocated >= s
void trimToSize()
{
if (allocated > size())
b.realloc(allocated = size());
}
bool canAppend(size_t s)
{
return allocated > b.len + s;
}
bool isAllocated(int8_t *p)
{
return p >= base() && p <= end();
} // asserts
void set(bytes &src)
{
set(src.ptr, src.len);
}
void set(int8_t *ptr, size_t len)
{
b.set(ptr, len);
allocated = 0; // mark as not reallocatable
}
void set(int8_t *ptr, size_t len)
{
b.set(ptr, len);
allocated = 0; // mark as not reallocatable
}
// block operations on resizing byte buffer:
fillbytes &append(const void *ptr_, size_t len_)
{
memcpy(grow(len_), ptr_, len_);
return (*this);
}
fillbytes &append(bytes &other)
{
return append(other.ptr, other.len);
}
fillbytes &append(const char *str)
{
return append(str, strlen(str));
}
// block operations on resizing byte buffer:
fillbytes &append(const void *ptr_, size_t len_)
{
memcpy(grow(len_), ptr_, len_);
return (*this);
}
fillbytes &append(bytes &other)
{
return append(other.ptr, other.len);
}
fillbytes &append(const char *str)
{
return append(str, strlen(str));
}
};
struct ptrlist : fillbytes
{
typedef const void *cvptr;
int length()
{
return (int)(size() / sizeof(cvptr));
}
cvptr *base()
{
return (cvptr *)fillbytes::base();
}
cvptr &get(int i)
{
return *(cvptr *)loc(i * sizeof(cvptr));
}
cvptr *limit()
{
return (cvptr *)fillbytes::limit();
}
void add(cvptr x)
{
*(cvptr *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(cvptr);
}
int indexOf(cvptr x);
bool contains(cvptr x)
{
return indexOf(x) >= 0;
}
void freeAll(); // frees every ptr on the list, plus the list itself
typedef const void *cvptr;
int length()
{
return (int)(size() / sizeof(cvptr));
}
cvptr *base()
{
return (cvptr *)fillbytes::base();
}
cvptr &get(int i)
{
return *(cvptr *)loc(i * sizeof(cvptr));
}
cvptr *limit()
{
return (cvptr *)fillbytes::limit();
}
void add(cvptr x)
{
*(cvptr *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(cvptr);
}
int indexOf(cvptr x);
bool contains(cvptr x)
{
return indexOf(x) >= 0;
}
void freeAll(); // frees every ptr on the list, plus the list itself
};
// Use a macro rather than mess with subtle mismatches
// between member and non-member function pointers.
@ -253,34 +253,34 @@ struct ptrlist : fillbytes
struct intlist : fillbytes
{
int length()
{
return (int)(size() / sizeof(int));
}
int *base()
{
return (int *)fillbytes::base();
}
int &get(int i)
{
return *(int *)loc(i * sizeof(int));
}
int *limit()
{
return (int *)fillbytes::limit();
}
void add(int x)
{
*(int *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(int);
}
int indexOf(int x);
bool contains(int x)
{
return indexOf(x) >= 0;
}
int length()
{
return (int)(size() / sizeof(int));
}
int *base()
{
return (int *)fillbytes::base();
}
int &get(int i)
{
return *(int *)loc(i * sizeof(int));
}
int *limit()
{
return (int *)fillbytes::limit();
}
void add(int x)
{
*(int *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(int);
}
int indexOf(int x);
bool contains(int x)
{
return indexOf(x) >= 0;
}
};

File diff suppressed because it is too large Load Diff

View File

@ -35,9 +35,9 @@ struct unpacker;
#define CODING_D(x) ((x) >> 0 & 0xF)
#define CODING_INIT(B, H, S, D) \
{ \
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
}
{ \
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
}
// For debugging purposes, some compilers do not like this and will complain.
// #define long do_not_use_C_long_types_use_jlong_or_int
@ -45,126 +45,126 @@ struct unpacker;
struct coding
{
int spec; // B,H,S,D
int spec; // B,H,S,D
// Handy values derived from the spec:
int B()
{
return CODING_B(spec);
}
int H()
{
return CODING_H(spec);
}
int S()
{
return CODING_S(spec);
}
int D()
{
return CODING_D(spec);
}
int L()
{
return 256 - CODING_H(spec);
}
int min, max;
int umin, umax;
char isSigned, isSubrange, isFullRange, isMalloc;
// Handy values derived from the spec:
int B()
{
return CODING_B(spec);
}
int H()
{
return CODING_H(spec);
}
int S()
{
return CODING_S(spec);
}
int D()
{
return CODING_D(spec);
}
int L()
{
return 256 - CODING_H(spec);
}
int min, max;
int umin, umax;
char isSigned, isSubrange, isFullRange, isMalloc;
coding *init(); // returns self or nullptr if error
coding *initFrom(int spec_)
{
assert(this->spec == 0);
this->spec = spec_;
return init();
}
coding *init(); // returns self or nullptr if error
coding *initFrom(int spec_)
{
assert(this->spec == 0);
this->spec = spec_;
return init();
}
static coding *findBySpec(int spec);
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
static coding *findByIndex(int irregularCodingIndex);
static coding *findBySpec(int spec);
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
static coding *findByIndex(int irregularCodingIndex);
static uint32_t parse(byte *&rp, int B, int H);
static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
static uint32_t parse(byte *&rp, int B, int H);
static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
uint32_t parse(byte *&rp)
{
return parse(rp, CODING_B(spec), CODING_H(spec));
}
void parseMultiple(byte *&rp, int N, byte *limit)
{
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
}
uint32_t parse(byte *&rp)
{
return parse(rp, CODING_B(spec), CODING_H(spec));
}
void parseMultiple(byte *&rp, int N, byte *limit)
{
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
}
bool canRepresent(int x)
{
return (x >= min && x <= max);
}
bool canRepresentUnsigned(int x)
{
return (x >= umin && x <= umax);
}
bool canRepresent(int x)
{
return (x >= min && x <= max);
}
bool canRepresentUnsigned(int x)
{
return (x >= umin && x <= umax);
}
int sumInUnsignedRange(int x, int y);
int sumInUnsignedRange(int x, int y);
int readFrom(byte *&rpVar, int *dbase);
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
void skipArrayFrom(byte *&rpVar, int length)
{
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
}
int readFrom(byte *&rpVar, int *dbase);
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
void skipArrayFrom(byte *&rpVar, int length)
{
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
}
void free(); // free self if isMalloc
void free(); // free self if isMalloc
};
enum coding_method_kind
{
cmk_ERROR,
cmk_BHS,
cmk_BHS0,
cmk_BHS1,
cmk_BHSD1,
cmk_BHS1D1full, // isFullRange
cmk_BHS1D1sub, // isSubRange
cmk_ERROR,
cmk_BHS,
cmk_BHS0,
cmk_BHS1,
cmk_BHSD1,
cmk_BHS1D1full, // isFullRange
cmk_BHS1D1sub, // isSubRange
// special cases hand-optimized (~50% of all decoded values)
cmk_BYTE1, //(1,256) 6%
cmk_CHAR3, //(3,128) 7%
cmk_UNSIGNED5, //(5,64) 13%
cmk_DELTA5, //(5,64,1,1) 5%
cmk_BCI5, //(5,4) 18%
cmk_BRANCH5, //(5,4,2) 4%
// cmk_UNSIGNED5H16, //(5,16) 5%
// cmk_UNSIGNED2H4, //(2,4) 6%
// cmk_DELTA4H8, //(4,8,1,1) 10%
// cmk_DELTA3H16, //(3,16,1,1) 9%
cmk_BHS_LIMIT,
cmk_pop,
cmk_pop_BHS0,
cmk_pop_BYTE1,
cmk_pop_LIMIT,
cmk_LIMIT
// special cases hand-optimized (~50% of all decoded values)
cmk_BYTE1, //(1,256) 6%
cmk_CHAR3, //(3,128) 7%
cmk_UNSIGNED5, //(5,64) 13%
cmk_DELTA5, //(5,64,1,1) 5%
cmk_BCI5, //(5,4) 18%
cmk_BRANCH5, //(5,4,2) 4%
// cmk_UNSIGNED5H16, //(5,16) 5%
// cmk_UNSIGNED2H4, //(2,4) 6%
// cmk_DELTA4H8, //(4,8,1,1) 10%
// cmk_DELTA3H16, //(3,16,1,1) 9%
cmk_BHS_LIMIT,
cmk_pop,
cmk_pop_BHS0,
cmk_pop_BYTE1,
cmk_pop_LIMIT,
cmk_LIMIT
};
enum
{
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
};
enum
{
B_MAX = 5,
C_SLOP = B_MAX * 10
B_MAX = 5,
C_SLOP = B_MAX * 10
};
struct coding_method;
@ -172,76 +172,76 @@ struct coding_method;
// iterator under the control of a meta-coding
struct value_stream
{
// current coding of values or values
coding c; // B,H,S,D,etc.
coding_method_kind cmk; // type of decoding needed
byte *rp; // read pointer
byte *rplimit; // final value of read pointer
int sum; // partial sum of all values so far (D=1 only)
coding_method *cm; // coding method that defines this stream
// current coding of values or values
coding c; // B,H,S,D,etc.
coding_method_kind cmk; // type of decoding needed
byte *rp; // read pointer
byte *rplimit; // final value of read pointer
int sum; // partial sum of all values so far (D=1 only)
coding_method *cm; // coding method that defines this stream
void init(byte *band_rp, byte *band_limit, coding *defc);
void init(byte *band_rp, byte *band_limit, int spec)
{
init(band_rp, band_limit, coding::findBySpec(spec));
}
void init(byte *band_rp, byte *band_limit, coding *defc);
void init(byte *band_rp, byte *band_limit, int spec)
{
init(band_rp, band_limit, coding::findBySpec(spec));
}
void setCoding(coding *c);
void setCoding(int spec)
{
setCoding(coding::findBySpec(spec));
}
void setCoding(coding *c);
void setCoding(int spec)
{
setCoding(coding::findBySpec(spec));
}
// Parse and decode a single value.
int getInt();
// Parse and decode a single value.
int getInt();
// Parse and decode a single byte, with no error checks.
int getByte()
{
assert(cmk == cmk_BYTE1);
assert(rp < rplimit);
return *rp++ & 0xFF;
}
// Parse and decode a single byte, with no error checks.
int getByte()
{
assert(cmk == cmk_BYTE1);
assert(rp < rplimit);
return *rp++ & 0xFF;
}
// Used only for asserts.
bool hasValue();
// Used only for asserts.
bool hasValue();
void done()
{
assert(!hasValue());
}
void done()
{
assert(!hasValue());
}
// Sometimes a value stream has an auxiliary (but there are never two).
value_stream *helper()
{
assert(hasHelper());
return this + 1;
}
bool hasHelper();
// Sometimes a value stream has an auxiliary (but there are never two).
value_stream *helper()
{
assert(hasHelper());
return this + 1;
}
bool hasHelper();
};
struct coding_method
{
value_stream vs0; // initial state snapshot (vs.meta==this)
value_stream vs0; // initial state snapshot (vs.meta==this)
coding_method *next; // what to do when we run out of bytes
coding_method *next; // what to do when we run out of bytes
// these fields are used for pop codes only:
int *fValues; // favored value array
int fVlength; // maximum favored value token
coding_method *uValues; // unfavored value stream
// these fields are used for pop codes only:
int *fValues; // favored value array
int fVlength; // maximum favored value token
coding_method *uValues; // unfavored value stream
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// Initialize a value stream.
void reset(value_stream *state);
// Initialize a value stream.
void reset(value_stream *state);
// Parse a band header, size a band, and initialize for further action.
// band_rp advances (but not past band_limit), and meta_rp advances.
// The mode gives context, such as "inside a pop".
// The defc and N are the incoming parameters to a meta-coding.
// The value sink is used to collect output values, when desired.
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
intlist *valueSink);
// Parse a band header, size a band, and initialize for further action.
// band_rp advances (but not past band_limit), and meta_rp advances.
// The mode gives context, such as "inside a pop".
// The defc and N are the incoming parameters to a meta-coding.
// The value sink is used to collect output values, when desired.
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
intlist *valueSink);
};

View File

@ -55,388 +55,388 @@
enum
{
CONSTANT_None,
CONSTANT_Utf8,
CONSTANT_unused2, /* unused, was Unicode */
CONSTANT_Integer,
CONSTANT_Float,
CONSTANT_Long,
CONSTANT_Double,
CONSTANT_Class,
CONSTANT_String,
CONSTANT_Fieldref,
CONSTANT_Methodref,
CONSTANT_InterfaceMethodref,
CONSTANT_NameandType,
CONSTANT_Signature = 13,
CONSTANT_All = 14,
CONSTANT_Limit = 15,
CONSTANT_NONE = 0,
CONSTANT_Literal = 20, // pseudo-tag for debugging
CONSTANT_Member = 21, // pseudo-tag for debugging
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
ACC_STATIC = 0x0008,
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
CLASS_ATTR_SourceFile = 17,
CLASS_ATTR_EnclosingMethod = 18,
CLASS_ATTR_InnerClasses = 23,
CLASS_ATTR_ClassFile_version = 24,
FIELD_ATTR_ConstantValue = 17,
METHOD_ATTR_Code = 17,
METHOD_ATTR_Exceptions = 18,
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
METHOD_ATTR_AnnotationDefault = 25,
CODE_ATTR_StackMapTable = 0,
CODE_ATTR_LineNumberTable = 1,
CODE_ATTR_LocalVariableTable = 2,
CODE_ATTR_LocalVariableTypeTable = 3,
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
X_ATTR_Signature = 19,
X_ATTR_Deprecated = 20,
X_ATTR_RuntimeVisibleAnnotations = 21,
X_ATTR_RuntimeInvisibleAnnotations = 22,
X_ATTR_OVERFLOW = 16,
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
X_ATTR_LIMIT_FLAGS_HI = 63,
CONSTANT_None,
CONSTANT_Utf8,
CONSTANT_unused2, /* unused, was Unicode */
CONSTANT_Integer,
CONSTANT_Float,
CONSTANT_Long,
CONSTANT_Double,
CONSTANT_Class,
CONSTANT_String,
CONSTANT_Fieldref,
CONSTANT_Methodref,
CONSTANT_InterfaceMethodref,
CONSTANT_NameandType,
CONSTANT_Signature = 13,
CONSTANT_All = 14,
CONSTANT_Limit = 15,
CONSTANT_NONE = 0,
CONSTANT_Literal = 20, // pseudo-tag for debugging
CONSTANT_Member = 21, // pseudo-tag for debugging
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
ACC_STATIC = 0x0008,
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
CLASS_ATTR_SourceFile = 17,
CLASS_ATTR_EnclosingMethod = 18,
CLASS_ATTR_InnerClasses = 23,
CLASS_ATTR_ClassFile_version = 24,
FIELD_ATTR_ConstantValue = 17,
METHOD_ATTR_Code = 17,
METHOD_ATTR_Exceptions = 18,
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
METHOD_ATTR_AnnotationDefault = 25,
CODE_ATTR_StackMapTable = 0,
CODE_ATTR_LineNumberTable = 1,
CODE_ATTR_LocalVariableTable = 2,
CODE_ATTR_LocalVariableTypeTable = 3,
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
X_ATTR_Signature = 19,
X_ATTR_Deprecated = 20,
X_ATTR_RuntimeVisibleAnnotations = 21,
X_ATTR_RuntimeInvisibleAnnotations = 22,
X_ATTR_OVERFLOW = 16,
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
X_ATTR_LIMIT_FLAGS_HI = 63,
#define O_ATTR_DO(F) \
F(X_ATTR_OVERFLOW, 01) \
/*(end)*/
F(X_ATTR_OVERFLOW, 01) \
/*(end)*/
#define X_ATTR_DO(F) \
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
/*F(X_ATTR_Synthetic,Synthetic)*/ \
/*(end)*/
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
/*F(X_ATTR_Synthetic,Synthetic)*/ \
/*(end)*/
#define CLASS_ATTR_DO(F) \
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
/*(end)*/
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
/*(end)*/
#define FIELD_ATTR_DO(F) \
F(FIELD_ATTR_ConstantValue, ConstantValue) \
/*(end)*/
F(FIELD_ATTR_ConstantValue, ConstantValue) \
/*(end)*/
#define METHOD_ATTR_DO(F) \
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
RuntimeInvisibleParameterAnnotations) \
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
/*(end)*/
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
RuntimeInvisibleParameterAnnotations) \
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
/*(end)*/
#define CODE_ATTR_DO(F) \
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
/*(end)*/
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
/*(end)*/
#define ALL_ATTR_DO(F) \
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
/*(end)*/
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
/*(end)*/
// attribute "context types"
ATTR_CONTEXT_CLASS = 0,
ATTR_CONTEXT_FIELD = 1,
ATTR_CONTEXT_METHOD = 2,
ATTR_CONTEXT_CODE = 3,
ATTR_CONTEXT_LIMIT = 4,
// attribute "context types"
ATTR_CONTEXT_CLASS = 0,
ATTR_CONTEXT_FIELD = 1,
ATTR_CONTEXT_METHOD = 2,
ATTR_CONTEXT_CODE = 3,
ATTR_CONTEXT_LIMIT = 4,
// constants for parsed layouts (stored in band::le_kind)
EK_NONE = 0, // not a layout element
EK_INT = 'I', // B H I SH etc., also FH etc.
EK_BCI = 'P', // PH etc.
EK_BCID = 'Q', // POH etc.
EK_BCO = 'O', // OH etc.
EK_REPL = 'N', // NH[...] etc.
EK_REF = 'R', // RUH, RUNH, KQH, etc.
EK_UN = 'T', // TB(...)[...] etc.
EK_CASE = 'K', // (...)[...] etc.
EK_CALL = '(', // (0), (1), etc.
EK_CBLE = '[', // [...][...] etc.
NO_BAND_INDEX = -1,
// constants for parsed layouts (stored in band::le_kind)
EK_NONE = 0, // not a layout element
EK_INT = 'I', // B H I SH etc., also FH etc.
EK_BCI = 'P', // PH etc.
EK_BCID = 'Q', // POH etc.
EK_BCO = 'O', // OH etc.
EK_REPL = 'N', // NH[...] etc.
EK_REF = 'R', // RUH, RUNH, KQH, etc.
EK_UN = 'T', // TB(...)[...] etc.
EK_CASE = 'K', // (...)[...] etc.
EK_CALL = '(', // (0), (1), etc.
EK_CBLE = '[', // [...][...] etc.
NO_BAND_INDEX = -1,
// File option bits, from LSB in ascending bit position.
FO_DEFLATE_HINT = 1 << 0,
FO_IS_CLASS_STUB = 1 << 1,
// File option bits, from LSB in ascending bit position.
FO_DEFLATE_HINT = 1 << 0,
FO_IS_CLASS_STUB = 1 << 1,
// Archive option bits, from LSB in ascending bit position:
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
AO_HAVE_CP_NUMBERS = 1 << 1,
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
AO_3_UNUSED_MBZ = 1 << 3,
AO_HAVE_FILE_HEADERS = 1 << 4,
AO_DEFLATE_HINT = 1 << 5,
AO_HAVE_FILE_MODTIME = 1 << 6,
AO_HAVE_FILE_OPTIONS = 1 << 7,
AO_HAVE_FILE_SIZE_HI = 1 << 8,
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
// Archive option bits, from LSB in ascending bit position:
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
AO_HAVE_CP_NUMBERS = 1 << 1,
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
AO_3_UNUSED_MBZ = 1 << 3,
AO_HAVE_FILE_HEADERS = 1 << 4,
AO_DEFLATE_HINT = 1 << 5,
AO_HAVE_FILE_MODTIME = 1 << 6,
AO_HAVE_FILE_OPTIONS = 1 << 7,
AO_HAVE_FILE_SIZE_HI = 1 << 8,
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
#define ARCHIVE_BIT_DO(F) \
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
/*F(AO_3_UNUSED_MBZ)*/ \
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
/*(end)*/
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
/*F(AO_3_UNUSED_MBZ)*/ \
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
/*(end)*/
// Constants for decoding attribute definition header bytes.
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
// Constants for decoding attribute definition header bytes.
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
NO_MODTIME = 0, // nullptr modtime value
NO_MODTIME = 0, // nullptr modtime value
// meta-coding
_meta_default = 0,
_meta_canon_min = 1,
_meta_canon_max = 115,
_meta_arb = 116,
_meta_run = 117,
_meta_pop = 141,
_meta_limit = 189,
_meta_error = 255,
_xxx_1_end
// meta-coding
_meta_default = 0,
_meta_canon_min = 1,
_meta_canon_max = 115,
_meta_arb = 116,
_meta_run = 117,
_meta_pop = 141,
_meta_limit = 189,
_meta_error = 255,
_xxx_1_end
};
// Bytecodes.
enum
{
bc_nop = 0, // 0x00
bc_aconst_null = 1, // 0x01
bc_iconst_m1 = 2, // 0x02
bc_iconst_0 = 3, // 0x03
bc_iconst_1 = 4, // 0x04
bc_iconst_2 = 5, // 0x05
bc_iconst_3 = 6, // 0x06
bc_iconst_4 = 7, // 0x07
bc_iconst_5 = 8, // 0x08
bc_lconst_0 = 9, // 0x09
bc_lconst_1 = 10, // 0x0a
bc_fconst_0 = 11, // 0x0b
bc_fconst_1 = 12, // 0x0c
bc_fconst_2 = 13, // 0x0d
bc_dconst_0 = 14, // 0x0e
bc_dconst_1 = 15, // 0x0f
bc_bipush = 16, // 0x10
bc_sipush = 17, // 0x11
bc_ldc = 18, // 0x12
bc_ldc_w = 19, // 0x13
bc_ldc2_w = 20, // 0x14
bc_iload = 21, // 0x15
bc_lload = 22, // 0x16
bc_fload = 23, // 0x17
bc_dload = 24, // 0x18
bc_aload = 25, // 0x19
bc_iload_0 = 26, // 0x1a
bc_iload_1 = 27, // 0x1b
bc_iload_2 = 28, // 0x1c
bc_iload_3 = 29, // 0x1d
bc_lload_0 = 30, // 0x1e
bc_lload_1 = 31, // 0x1f
bc_lload_2 = 32, // 0x20
bc_lload_3 = 33, // 0x21
bc_fload_0 = 34, // 0x22
bc_fload_1 = 35, // 0x23
bc_fload_2 = 36, // 0x24
bc_fload_3 = 37, // 0x25
bc_dload_0 = 38, // 0x26
bc_dload_1 = 39, // 0x27
bc_dload_2 = 40, // 0x28
bc_dload_3 = 41, // 0x29
bc_aload_0 = 42, // 0x2a
bc_aload_1 = 43, // 0x2b
bc_aload_2 = 44, // 0x2c
bc_aload_3 = 45, // 0x2d
bc_iaload = 46, // 0x2e
bc_laload = 47, // 0x2f
bc_faload = 48, // 0x30
bc_daload = 49, // 0x31
bc_aaload = 50, // 0x32
bc_baload = 51, // 0x33
bc_caload = 52, // 0x34
bc_saload = 53, // 0x35
bc_istore = 54, // 0x36
bc_lstore = 55, // 0x37
bc_fstore = 56, // 0x38
bc_dstore = 57, // 0x39
bc_astore = 58, // 0x3a
bc_istore_0 = 59, // 0x3b
bc_istore_1 = 60, // 0x3c
bc_istore_2 = 61, // 0x3d
bc_istore_3 = 62, // 0x3e
bc_lstore_0 = 63, // 0x3f
bc_lstore_1 = 64, // 0x40
bc_lstore_2 = 65, // 0x41
bc_lstore_3 = 66, // 0x42
bc_fstore_0 = 67, // 0x43
bc_fstore_1 = 68, // 0x44
bc_fstore_2 = 69, // 0x45
bc_fstore_3 = 70, // 0x46
bc_dstore_0 = 71, // 0x47
bc_dstore_1 = 72, // 0x48
bc_dstore_2 = 73, // 0x49
bc_dstore_3 = 74, // 0x4a
bc_astore_0 = 75, // 0x4b
bc_astore_1 = 76, // 0x4c
bc_astore_2 = 77, // 0x4d
bc_astore_3 = 78, // 0x4e
bc_iastore = 79, // 0x4f
bc_lastore = 80, // 0x50
bc_fastore = 81, // 0x51
bc_dastore = 82, // 0x52
bc_aastore = 83, // 0x53
bc_bastore = 84, // 0x54
bc_castore = 85, // 0x55
bc_sastore = 86, // 0x56
bc_pop = 87, // 0x57
bc_pop2 = 88, // 0x58
bc_dup = 89, // 0x59
bc_dup_x1 = 90, // 0x5a
bc_dup_x2 = 91, // 0x5b
bc_dup2 = 92, // 0x5c
bc_dup2_x1 = 93, // 0x5d
bc_dup2_x2 = 94, // 0x5e
bc_swap = 95, // 0x5f
bc_iadd = 96, // 0x60
bc_ladd = 97, // 0x61
bc_fadd = 98, // 0x62
bc_dadd = 99, // 0x63
bc_isub = 100, // 0x64
bc_lsub = 101, // 0x65
bc_fsub = 102, // 0x66
bc_dsub = 103, // 0x67
bc_imul = 104, // 0x68
bc_lmul = 105, // 0x69
bc_fmul = 106, // 0x6a
bc_dmul = 107, // 0x6b
bc_idiv = 108, // 0x6c
bc_ldiv = 109, // 0x6d
bc_fdiv = 110, // 0x6e
bc_ddiv = 111, // 0x6f
bc_irem = 112, // 0x70
bc_lrem = 113, // 0x71
bc_frem = 114, // 0x72
bc_drem = 115, // 0x73
bc_ineg = 116, // 0x74
bc_lneg = 117, // 0x75
bc_fneg = 118, // 0x76
bc_dneg = 119, // 0x77
bc_ishl = 120, // 0x78
bc_lshl = 121, // 0x79
bc_ishr = 122, // 0x7a
bc_lshr = 123, // 0x7b
bc_iushr = 124, // 0x7c
bc_lushr = 125, // 0x7d
bc_iand = 126, // 0x7e
bc_land = 127, // 0x7f
bc_ior = 128, // 0x80
bc_lor = 129, // 0x81
bc_ixor = 130, // 0x82
bc_lxor = 131, // 0x83
bc_iinc = 132, // 0x84
bc_i2l = 133, // 0x85
bc_i2f = 134, // 0x86
bc_i2d = 135, // 0x87
bc_l2i = 136, // 0x88
bc_l2f = 137, // 0x89
bc_l2d = 138, // 0x8a
bc_f2i = 139, // 0x8b
bc_f2l = 140, // 0x8c
bc_f2d = 141, // 0x8d
bc_d2i = 142, // 0x8e
bc_d2l = 143, // 0x8f
bc_d2f = 144, // 0x90
bc_i2b = 145, // 0x91
bc_i2c = 146, // 0x92
bc_i2s = 147, // 0x93
bc_lcmp = 148, // 0x94
bc_fcmpl = 149, // 0x95
bc_fcmpg = 150, // 0x96
bc_dcmpl = 151, // 0x97
bc_dcmpg = 152, // 0x98
bc_ifeq = 153, // 0x99
bc_ifne = 154, // 0x9a
bc_iflt = 155, // 0x9b
bc_ifge = 156, // 0x9c
bc_ifgt = 157, // 0x9d
bc_ifle = 158, // 0x9e
bc_if_icmpeq = 159, // 0x9f
bc_if_icmpne = 160, // 0xa0
bc_if_icmplt = 161, // 0xa1
bc_if_icmpge = 162, // 0xa2
bc_if_icmpgt = 163, // 0xa3
bc_if_icmple = 164, // 0xa4
bc_if_acmpeq = 165, // 0xa5
bc_if_acmpne = 166, // 0xa6
bc_goto = 167, // 0xa7
bc_jsr = 168, // 0xa8
bc_ret = 169, // 0xa9
bc_tableswitch = 170, // 0xaa
bc_lookupswitch = 171, // 0xab
bc_ireturn = 172, // 0xac
bc_lreturn = 173, // 0xad
bc_freturn = 174, // 0xae
bc_dreturn = 175, // 0xaf
bc_areturn = 176, // 0xb0
bc_return = 177, // 0xb1
bc_getstatic = 178, // 0xb2
bc_putstatic = 179, // 0xb3
bc_getfield = 180, // 0xb4
bc_putfield = 181, // 0xb5
bc_invokevirtual = 182, // 0xb6
bc_invokespecial = 183, // 0xb7
bc_invokestatic = 184, // 0xb8
bc_invokeinterface = 185, // 0xb9
bc_xxxunusedxxx = 186, // 0xba
bc_new = 187, // 0xbb
bc_newarray = 188, // 0xbc
bc_anewarray = 189, // 0xbd
bc_arraylength = 190, // 0xbe
bc_athrow = 191, // 0xbf
bc_checkcast = 192, // 0xc0
bc_instanceof = 193, // 0xc1
bc_monitorenter = 194, // 0xc2
bc_monitorexit = 195, // 0xc3
bc_wide = 196, // 0xc4
bc_multianewarray = 197, // 0xc5
bc_ifnull = 198, // 0xc6
bc_ifnonnull = 199, // 0xc7
bc_goto_w = 200, // 0xc8
bc_jsr_w = 201, // 0xc9
bc_bytecode_limit = 202 // 0xca
bc_nop = 0, // 0x00
bc_aconst_null = 1, // 0x01
bc_iconst_m1 = 2, // 0x02
bc_iconst_0 = 3, // 0x03
bc_iconst_1 = 4, // 0x04
bc_iconst_2 = 5, // 0x05
bc_iconst_3 = 6, // 0x06
bc_iconst_4 = 7, // 0x07
bc_iconst_5 = 8, // 0x08
bc_lconst_0 = 9, // 0x09
bc_lconst_1 = 10, // 0x0a
bc_fconst_0 = 11, // 0x0b
bc_fconst_1 = 12, // 0x0c
bc_fconst_2 = 13, // 0x0d
bc_dconst_0 = 14, // 0x0e
bc_dconst_1 = 15, // 0x0f
bc_bipush = 16, // 0x10
bc_sipush = 17, // 0x11
bc_ldc = 18, // 0x12
bc_ldc_w = 19, // 0x13
bc_ldc2_w = 20, // 0x14
bc_iload = 21, // 0x15
bc_lload = 22, // 0x16
bc_fload = 23, // 0x17
bc_dload = 24, // 0x18
bc_aload = 25, // 0x19
bc_iload_0 = 26, // 0x1a
bc_iload_1 = 27, // 0x1b
bc_iload_2 = 28, // 0x1c
bc_iload_3 = 29, // 0x1d
bc_lload_0 = 30, // 0x1e
bc_lload_1 = 31, // 0x1f
bc_lload_2 = 32, // 0x20
bc_lload_3 = 33, // 0x21
bc_fload_0 = 34, // 0x22
bc_fload_1 = 35, // 0x23
bc_fload_2 = 36, // 0x24
bc_fload_3 = 37, // 0x25
bc_dload_0 = 38, // 0x26
bc_dload_1 = 39, // 0x27
bc_dload_2 = 40, // 0x28
bc_dload_3 = 41, // 0x29
bc_aload_0 = 42, // 0x2a
bc_aload_1 = 43, // 0x2b
bc_aload_2 = 44, // 0x2c
bc_aload_3 = 45, // 0x2d
bc_iaload = 46, // 0x2e
bc_laload = 47, // 0x2f
bc_faload = 48, // 0x30
bc_daload = 49, // 0x31
bc_aaload = 50, // 0x32
bc_baload = 51, // 0x33
bc_caload = 52, // 0x34
bc_saload = 53, // 0x35
bc_istore = 54, // 0x36
bc_lstore = 55, // 0x37
bc_fstore = 56, // 0x38
bc_dstore = 57, // 0x39
bc_astore = 58, // 0x3a
bc_istore_0 = 59, // 0x3b
bc_istore_1 = 60, // 0x3c
bc_istore_2 = 61, // 0x3d
bc_istore_3 = 62, // 0x3e
bc_lstore_0 = 63, // 0x3f
bc_lstore_1 = 64, // 0x40
bc_lstore_2 = 65, // 0x41
bc_lstore_3 = 66, // 0x42
bc_fstore_0 = 67, // 0x43
bc_fstore_1 = 68, // 0x44
bc_fstore_2 = 69, // 0x45
bc_fstore_3 = 70, // 0x46
bc_dstore_0 = 71, // 0x47
bc_dstore_1 = 72, // 0x48
bc_dstore_2 = 73, // 0x49
bc_dstore_3 = 74, // 0x4a
bc_astore_0 = 75, // 0x4b
bc_astore_1 = 76, // 0x4c
bc_astore_2 = 77, // 0x4d
bc_astore_3 = 78, // 0x4e
bc_iastore = 79, // 0x4f
bc_lastore = 80, // 0x50
bc_fastore = 81, // 0x51
bc_dastore = 82, // 0x52
bc_aastore = 83, // 0x53
bc_bastore = 84, // 0x54
bc_castore = 85, // 0x55
bc_sastore = 86, // 0x56
bc_pop = 87, // 0x57
bc_pop2 = 88, // 0x58
bc_dup = 89, // 0x59
bc_dup_x1 = 90, // 0x5a
bc_dup_x2 = 91, // 0x5b
bc_dup2 = 92, // 0x5c
bc_dup2_x1 = 93, // 0x5d
bc_dup2_x2 = 94, // 0x5e
bc_swap = 95, // 0x5f
bc_iadd = 96, // 0x60
bc_ladd = 97, // 0x61
bc_fadd = 98, // 0x62
bc_dadd = 99, // 0x63
bc_isub = 100, // 0x64
bc_lsub = 101, // 0x65
bc_fsub = 102, // 0x66
bc_dsub = 103, // 0x67
bc_imul = 104, // 0x68
bc_lmul = 105, // 0x69
bc_fmul = 106, // 0x6a
bc_dmul = 107, // 0x6b
bc_idiv = 108, // 0x6c
bc_ldiv = 109, // 0x6d
bc_fdiv = 110, // 0x6e
bc_ddiv = 111, // 0x6f
bc_irem = 112, // 0x70
bc_lrem = 113, // 0x71
bc_frem = 114, // 0x72
bc_drem = 115, // 0x73
bc_ineg = 116, // 0x74
bc_lneg = 117, // 0x75
bc_fneg = 118, // 0x76
bc_dneg = 119, // 0x77
bc_ishl = 120, // 0x78
bc_lshl = 121, // 0x79
bc_ishr = 122, // 0x7a
bc_lshr = 123, // 0x7b
bc_iushr = 124, // 0x7c
bc_lushr = 125, // 0x7d
bc_iand = 126, // 0x7e
bc_land = 127, // 0x7f
bc_ior = 128, // 0x80
bc_lor = 129, // 0x81
bc_ixor = 130, // 0x82
bc_lxor = 131, // 0x83
bc_iinc = 132, // 0x84
bc_i2l = 133, // 0x85
bc_i2f = 134, // 0x86
bc_i2d = 135, // 0x87
bc_l2i = 136, // 0x88
bc_l2f = 137, // 0x89
bc_l2d = 138, // 0x8a
bc_f2i = 139, // 0x8b
bc_f2l = 140, // 0x8c
bc_f2d = 141, // 0x8d
bc_d2i = 142, // 0x8e
bc_d2l = 143, // 0x8f
bc_d2f = 144, // 0x90
bc_i2b = 145, // 0x91
bc_i2c = 146, // 0x92
bc_i2s = 147, // 0x93
bc_lcmp = 148, // 0x94
bc_fcmpl = 149, // 0x95
bc_fcmpg = 150, // 0x96
bc_dcmpl = 151, // 0x97
bc_dcmpg = 152, // 0x98
bc_ifeq = 153, // 0x99
bc_ifne = 154, // 0x9a
bc_iflt = 155, // 0x9b
bc_ifge = 156, // 0x9c
bc_ifgt = 157, // 0x9d
bc_ifle = 158, // 0x9e
bc_if_icmpeq = 159, // 0x9f
bc_if_icmpne = 160, // 0xa0
bc_if_icmplt = 161, // 0xa1
bc_if_icmpge = 162, // 0xa2
bc_if_icmpgt = 163, // 0xa3
bc_if_icmple = 164, // 0xa4
bc_if_acmpeq = 165, // 0xa5
bc_if_acmpne = 166, // 0xa6
bc_goto = 167, // 0xa7
bc_jsr = 168, // 0xa8
bc_ret = 169, // 0xa9
bc_tableswitch = 170, // 0xaa
bc_lookupswitch = 171, // 0xab
bc_ireturn = 172, // 0xac
bc_lreturn = 173, // 0xad
bc_freturn = 174, // 0xae
bc_dreturn = 175, // 0xaf
bc_areturn = 176, // 0xb0
bc_return = 177, // 0xb1
bc_getstatic = 178, // 0xb2
bc_putstatic = 179, // 0xb3
bc_getfield = 180, // 0xb4
bc_putfield = 181, // 0xb5
bc_invokevirtual = 182, // 0xb6
bc_invokespecial = 183, // 0xb7
bc_invokestatic = 184, // 0xb8
bc_invokeinterface = 185, // 0xb9
bc_xxxunusedxxx = 186, // 0xba
bc_new = 187, // 0xbb
bc_newarray = 188, // 0xbc
bc_anewarray = 189, // 0xbd
bc_arraylength = 190, // 0xbe
bc_athrow = 191, // 0xbf
bc_checkcast = 192, // 0xc0
bc_instanceof = 193, // 0xc1
bc_monitorenter = 194, // 0xc2
bc_monitorexit = 195, // 0xc3
bc_wide = 196, // 0xc4
bc_multianewarray = 197, // 0xc5
bc_ifnull = 198, // 0xc6
bc_ifnonnull = 199, // 0xc7
bc_goto_w = 200, // 0xc8
bc_jsr_w = 201, // 0xc9
bc_bytecode_limit = 202 // 0xca
};
enum
{
bc_end_marker = 255,
bc_byte_escape = 254,
bc_ref_escape = 253,
_first_linker_op = bc_getstatic,
_last_linker_op = bc_invokestatic,
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
_self_linker_op = bc_bytecode_limit,
_self_linker_aload_flag = 1 * _num_linker_ops,
_self_linker_super_flag = 2 * _num_linker_ops,
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
_invokeinit_op = _self_linker_limit,
_invokeinit_self_option = 0,
_invokeinit_super_option = 1,
_invokeinit_new_option = 2,
_invokeinit_limit = _invokeinit_op + 3,
_xldc_op = _invokeinit_limit,
bc_aldc = bc_ldc,
bc_cldc = _xldc_op + 0,
bc_ildc = _xldc_op + 1,
bc_fldc = _xldc_op + 2,
bc_aldc_w = bc_ldc_w,
bc_cldc_w = _xldc_op + 3,
bc_ildc_w = _xldc_op + 4,
bc_fldc_w = _xldc_op + 5,
bc_lldc2_w = bc_ldc2_w,
bc_dldc2_w = _xldc_op + 6,
_xldc_limit = _xldc_op + 7,
_xxx_3_end
bc_end_marker = 255,
bc_byte_escape = 254,
bc_ref_escape = 253,
_first_linker_op = bc_getstatic,
_last_linker_op = bc_invokestatic,
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
_self_linker_op = bc_bytecode_limit,
_self_linker_aload_flag = 1 * _num_linker_ops,
_self_linker_super_flag = 2 * _num_linker_ops,
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
_invokeinit_op = _self_linker_limit,
_invokeinit_self_option = 0,
_invokeinit_super_option = 1,
_invokeinit_new_option = 2,
_invokeinit_limit = _invokeinit_op + 3,
_xldc_op = _invokeinit_limit,
bc_aldc = bc_ldc,
bc_cldc = _xldc_op + 0,
bc_ildc = _xldc_op + 1,
bc_fldc = _xldc_op + 2,
bc_aldc_w = bc_ldc_w,
bc_cldc_w = _xldc_op + 3,
bc_ildc_w = _xldc_op + 4,
bc_fldc_w = _xldc_op + 5,
bc_lldc2_w = bc_ldc2_w,
bc_dldc2_w = _xldc_op + 6,
_xldc_limit = _xldc_op + 7,
_xxx_3_end
};

File diff suppressed because it is too large Load Diff

View File

@ -35,104 +35,104 @@ struct value_stream;
struct cpindex
{
uint32_t len;
entry *base1; // base of primary index
entry **base2; // base of secondary index
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
enum
{
SUB_TAG = 64
};
uint32_t len;
entry *base1; // base of primary index
entry **base2; // base of secondary index
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
enum
{
SUB_TAG = 64
};
entry *get(uint32_t i);
entry *get(uint32_t i);
void init(int len_, entry *base1_, int ixTag_)
{
len = len_;
base1 = base1_;
base2 = nullptr;
ixTag = ixTag_;
}
void init(int len_, entry **base2_, int ixTag_)
{
len = len_;
base1 = nullptr;
base2 = base2_;
ixTag = ixTag_;
}
void init(int len_, entry *base1_, int ixTag_)
{
len = len_;
base1 = base1_;
base2 = nullptr;
ixTag = ixTag_;
}
void init(int len_, entry **base2_, int ixTag_)
{
len = len_;
base1 = nullptr;
base2 = base2_;
ixTag = ixTag_;
}
};
struct constant_pool
{
uint32_t nentries;
entry *entries;
entry *first_extra_entry;
uint32_t maxentries; // total allocated size of entries
uint32_t nentries;
entry *entries;
entry *first_extra_entry;
uint32_t maxentries; // total allocated size of entries
// Position and size of each homogeneous subrange:
int tag_count[CONSTANT_Limit];
int tag_base[CONSTANT_Limit];
cpindex tag_index[CONSTANT_Limit];
ptrlist tag_extras[CONSTANT_Limit];
// Position and size of each homogeneous subrange:
int tag_count[CONSTANT_Limit];
int tag_base[CONSTANT_Limit];
cpindex tag_index[CONSTANT_Limit];
ptrlist tag_extras[CONSTANT_Limit];
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
cpindex *getFieldIndex(entry *classRef);
cpindex *getMethodIndex(entry *classRef);
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
cpindex *getFieldIndex(entry *classRef);
cpindex *getMethodIndex(entry *classRef);
inner_class **ic_index;
inner_class **ic_child_index;
inner_class *getIC(entry *inner);
inner_class *getFirstChildIC(entry *outer);
inner_class *getNextChildIC(inner_class *child);
inner_class **ic_index;
inner_class **ic_child_index;
inner_class *getIC(entry *inner);
inner_class *getFirstChildIC(entry *outer);
inner_class *getNextChildIC(inner_class *child);
int outputIndexLimit; // index limit after renumbering
ptrlist outputEntries; // list of entry* needing output idx assigned
int outputIndexLimit; // index limit after renumbering
ptrlist outputEntries; // list of entry* needing output idx assigned
entry **hashTab;
uint32_t hashTabLength;
entry *&hashTabRef(byte tag, bytes &b);
entry *ensureUtf8(bytes &b);
entry *ensureClass(bytes &b);
entry **hashTab;
uint32_t hashTabLength;
entry *&hashTabRef(byte tag, bytes &b);
entry *ensureUtf8(bytes &b);
entry *ensureClass(bytes &b);
// Well-known Utf8 symbols.
enum
{
// Well-known Utf8 symbols.
enum
{
#define SNAME(n, s) s_##s,
ALL_ATTR_DO(SNAME)
ALL_ATTR_DO(SNAME)
#undef SNAME
s_lt_init_gt, // <init>
s_LIMIT
};
entry *sym[s_LIMIT];
s_lt_init_gt, // <init>
s_LIMIT
};
entry *sym[s_LIMIT];
// read counts from hdr, allocate main arrays
enum
{
NUM_COUNTS = 12
};
void init(unpacker *u, int counts[NUM_COUNTS]);
// read counts from hdr, allocate main arrays
enum
{
NUM_COUNTS = 12
};
void init(unpacker *u, int counts[NUM_COUNTS]);
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// pointer to outer unpacker, for error checks etc.
unpacker *u;
int getCount(byte tag)
{
assert((uint32_t)tag < CONSTANT_Limit);
return tag_count[tag];
}
cpindex *getIndex(byte tag)
{
assert((uint32_t)tag < CONSTANT_Limit);
return &tag_index[tag];
}
cpindex *getKQIndex(); // uses cur_descr
int getCount(byte tag)
{
assert((uint32_t)tag < CONSTANT_Limit);
return tag_count[tag];
}
cpindex *getIndex(byte tag)
{
assert((uint32_t)tag < CONSTANT_Limit);
return &tag_index[tag];
}
cpindex *getKQIndex(); // uses cur_descr
void expandSignatures();
void initMemberIndexes();
void expandSignatures();
void initMemberIndexes();
void computeOutputOrder();
void computeOutputIndexes();
void resetOutputIndexes();
void computeOutputOrder();
void computeOutputIndexes();
void resetOutputIndexes();
};
/*
@ -141,407 +141,407 @@ struct constant_pool
*/
struct unpacker
{
// One element of the resulting JAR.
struct file
{
const char *name;
uint64_t size;
int modtime;
int options;
bytes data[2];
// Note: If Sum(data[*].len) < size,
// remaining bytes must be read directly from the input stream.
bool deflate_hint()
{
return ((options & FO_DEFLATE_HINT) != 0);
}
};
// One element of the resulting JAR.
struct file
{
const char *name;
uint64_t size;
int modtime;
int options;
bytes data[2];
// Note: If Sum(data[*].len) < size,
// remaining bytes must be read directly from the input stream.
bool deflate_hint()
{
return ((options & FO_DEFLATE_HINT) != 0);
}
};
// if running Unix-style, here are the inputs and outputs
FILE *infileptr; // buffered
bytes inbytes; // direct
gunzip *gzin; // gunzip filter, if any
jar *jarout; // output JAR file
// if running Unix-style, here are the inputs and outputs
FILE *infileptr; // buffered
bytes inbytes; // direct
gunzip *gzin; // gunzip filter, if any
jar *jarout; // output JAR file
// pointer to self, for U_NEW macro
unpacker *u;
// pointer to self, for U_NEW macro
unpacker *u;
ptrlist mallocs; // list of guys to free when we are all done
ptrlist tmallocs; // list of guys to free on next client request
fillbytes smallbuf; // supplies small alloc requests
fillbytes tsmallbuf; // supplies temporary small alloc requests
ptrlist mallocs; // list of guys to free when we are all done
ptrlist tmallocs; // list of guys to free on next client request
fillbytes smallbuf; // supplies small alloc requests
fillbytes tsmallbuf; // supplies temporary small alloc requests
// option management members
int verbose; // verbose level, 0 means no output
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
int modification_time_or_zero;
// option management members
int verbose; // verbose level, 0 means no output
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
int modification_time_or_zero;
// input stream
fillbytes input; // the whole block (size is predicted, has slop too)
bool live_input; // is the data in this block live?
bool free_input; // must the input buffer be freed?
byte *rp; // read pointer (< rplimit <= input.limit())
byte *rplimit; // how much of the input block has been read?
uint64_t bytes_read;
int unsized_bytes_read;
// input stream
fillbytes input; // the whole block (size is predicted, has slop too)
bool live_input; // is the data in this block live?
bool free_input; // must the input buffer be freed?
byte *rp; // read pointer (< rplimit <= input.limit())
byte *rplimit; // how much of the input block has been read?
uint64_t bytes_read;
int unsized_bytes_read;
// callback to read at least one byte, up to available input
typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen,
int64_t maxlen);
read_input_fn_t read_input_fn;
// callback to read at least one byte, up to available input
typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen,
int64_t maxlen);
read_input_fn_t read_input_fn;
// archive header fields
int magic, minver, majver;
size_t archive_size;
int archive_next_count, archive_options, archive_modtime;
int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count;
int default_class_minver, default_class_majver;
int default_file_options, suppress_file_options; // not header fields
int default_archive_modtime, default_file_modtime; // not header fields
int code_count; // not a header field
int files_remaining; // not a header field
// archive header fields
int magic, minver, majver;
size_t archive_size;
int archive_next_count, archive_options, archive_modtime;
int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count;
int default_class_minver, default_class_majver;
int default_file_options, suppress_file_options; // not header fields
int default_archive_modtime, default_file_modtime; // not header fields
int code_count; // not a header field
int files_remaining; // not a header field
// engine state
band *all_bands; // indexed by band_number
byte *meta_rp; // read-pointer into (copy of) band_headers
constant_pool cp; // all constant pool information
inner_class *ics; // InnerClasses
// engine state
band *all_bands; // indexed by band_number
byte *meta_rp; // read-pointer into (copy of) band_headers
constant_pool cp; // all constant pool information
inner_class *ics; // InnerClasses
// output stream
bytes output; // output block (either classfile head or tail)
byte *wp; // write pointer (< wplimit == output.limit())
byte *wpbase; // write pointer starting address (<= wp)
byte *wplimit; // how much of the output block has been written?
// output stream
bytes output; // output block (either classfile head or tail)
byte *wp; // write pointer (< wplimit == output.limit())
byte *wpbase; // write pointer starting address (<= wp)
byte *wplimit; // how much of the output block has been written?
// output state
file cur_file;
entry *cur_class; // CONSTANT_Class entry
entry *cur_super; // CONSTANT_Class entry or nullptr
entry *cur_descr; // CONSTANT_NameandType entry
int cur_descr_flags; // flags corresponding to cur_descr
int cur_class_minver, cur_class_majver;
bool cur_class_has_local_ics;
fillbytes cur_classfile_head;
fillbytes cur_classfile_tail;
int files_written; // also tells which file we're working on
int classes_written; // also tells which class we're working on
uint64_t bytes_written;
intlist bcimap;
fillbytes class_fixup_type;
intlist class_fixup_offset;
ptrlist class_fixup_ref;
fillbytes code_fixup_type; // which format of branch operand?
intlist code_fixup_offset; // location of operand needing fixup
intlist code_fixup_source; // encoded ID of branch insn
ptrlist requested_ics; // which ics need output?
// output state
file cur_file;
entry *cur_class; // CONSTANT_Class entry
entry *cur_super; // CONSTANT_Class entry or nullptr
entry *cur_descr; // CONSTANT_NameandType entry
int cur_descr_flags; // flags corresponding to cur_descr
int cur_class_minver, cur_class_majver;
bool cur_class_has_local_ics;
fillbytes cur_classfile_head;
fillbytes cur_classfile_tail;
int files_written; // also tells which file we're working on
int classes_written; // also tells which class we're working on
uint64_t bytes_written;
intlist bcimap;
fillbytes class_fixup_type;
intlist class_fixup_offset;
ptrlist class_fixup_ref;
fillbytes code_fixup_type; // which format of branch operand?
intlist code_fixup_offset; // location of operand needing fixup
intlist code_fixup_source; // encoded ID of branch insn
ptrlist requested_ics; // which ics need output?
// stats pertaining to multiple segments (updated on reset)
uint64_t bytes_read_before_reset;
uint64_t bytes_written_before_reset;
int files_written_before_reset;
int classes_written_before_reset;
int segments_read_before_reset;
// stats pertaining to multiple segments (updated on reset)
uint64_t bytes_read_before_reset;
uint64_t bytes_written_before_reset;
int files_written_before_reset;
int classes_written_before_reset;
int segments_read_before_reset;
// attribute state
struct layout_definition
{
uint32_t idx; // index (0..31...) which identifies this layout
const char *name; // name of layout
entry *nameEntry;
const char *layout; // string of layout (not yet parsed)
band **elems; // array of top-level layout elems (or callables)
// attribute state
struct layout_definition
{
uint32_t idx; // index (0..31...) which identifies this layout
const char *name; // name of layout
entry *nameEntry;
const char *layout; // string of layout (not yet parsed)
band **elems; // array of top-level layout elems (or callables)
bool hasCallables()
{
return layout[0] == '[';
}
band **bands()
{
assert(elems != nullptr);
return elems;
}
};
struct attr_definitions
{
unpacker *u; // pointer to self, for U_NEW macro
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
int attrc; // ATTR_CONTEXT_CLASS, etc.
uint32_t flag_limit; // 32 or 63, depending on archive_options bit
uint64_t predef; // mask of built-in definitions
uint64_t redef; // mask of local flag definitions or redefinitions
ptrlist layouts; // local (compressor-defined) defs, in index order
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
intlist overflow_count;
ptrlist strip_names; // what attribute names are being stripped?
ptrlist band_stack; // Temp., used during layout parsing.
ptrlist calls_to_link; // (ditto)
int bands_made; // (ditto)
bool hasCallables()
{
return layout[0] == '[';
}
band **bands()
{
assert(elems != nullptr);
return elems;
}
};
struct attr_definitions
{
unpacker *u; // pointer to self, for U_NEW macro
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
int attrc; // ATTR_CONTEXT_CLASS, etc.
uint32_t flag_limit; // 32 or 63, depending on archive_options bit
uint64_t predef; // mask of built-in definitions
uint64_t redef; // mask of local flag definitions or redefinitions
ptrlist layouts; // local (compressor-defined) defs, in index order
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
intlist overflow_count;
ptrlist strip_names; // what attribute names are being stripped?
ptrlist band_stack; // Temp., used during layout parsing.
ptrlist calls_to_link; // (ditto)
int bands_made; // (ditto)
void free()
{
layouts.free();
overflow_count.free();
strip_names.free();
band_stack.free();
calls_to_link.free();
}
void free()
{
layouts.free();
overflow_count.free();
strip_names.free();
band_stack.free();
calls_to_link.free();
}
// Locate the five fixed bands.
band &xxx_flags_hi();
band &xxx_flags_lo();
band &xxx_attr_count();
band &xxx_attr_indexes();
band &xxx_attr_calls();
band &fixed_band(int e_class_xxx);
// Locate the five fixed bands.
band &xxx_flags_hi();
band &xxx_flags_lo();
band &xxx_attr_count();
band &xxx_attr_indexes();
band &xxx_attr_calls();
band &fixed_band(int e_class_xxx);
// Register a new layout, and make bands for it.
layout_definition *defineLayout(int idx, const char *name, const char *layout);
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
band **buildBands(layout_definition *lo);
// Register a new layout, and make bands for it.
layout_definition *defineLayout(int idx, const char *name, const char *layout);
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
band **buildBands(layout_definition *lo);
// Parse a layout string or part of one, recursively if necessary.
const char *parseLayout(const char *lp, band **&res, int curCble);
const char *parseNumeral(const char *lp, int &res);
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
bool can_be_signed = false);
band **popBody(int band_stack_base); // pops a body off band_stack
// Parse a layout string or part of one, recursively if necessary.
const char *parseLayout(const char *lp, band **&res, int curCble);
const char *parseNumeral(const char *lp, int &res);
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
bool can_be_signed = false);
band **popBody(int band_stack_base); // pops a body off band_stack
// Read data into the bands of the idx-th layout.
void readBandData(int idx); // parse layout, make bands, read data
void readBandData(band **body, uint32_t count); // recursive helper
// Read data into the bands of the idx-th layout.
void readBandData(int idx); // parse layout, make bands, read data
void readBandData(band **body, uint32_t count); // recursive helper
layout_definition *getLayout(uint32_t idx)
{
if (idx >= (uint32_t)layouts.length())
return nullptr;
return (layout_definition *)layouts.get(idx);
}
layout_definition *getLayout(uint32_t idx)
{
if (idx >= (uint32_t)layouts.length())
return nullptr;
return (layout_definition *)layouts.get(idx);
}
void setHaveLongFlags(bool z)
{
assert(flag_limit == 0); // not set up yet
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
}
bool haveLongFlags()
{
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
}
void setHaveLongFlags(bool z)
{
assert(flag_limit == 0); // not set up yet
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
}
bool haveLongFlags()
{
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
}
// Return flag_count if idx is predef and not redef, else zero.
int predefCount(uint32_t idx);
// Return flag_count if idx is predef and not redef, else zero.
int predefCount(uint32_t idx);
bool isRedefined(uint32_t idx)
{
if (idx >= flag_limit)
return false;
return (bool)((redef >> idx) & 1);
}
bool isPredefined(uint32_t idx)
{
if (idx >= flag_limit)
return false;
return (bool)(((predef & ~redef) >> idx) & 1);
}
uint64_t flagIndexMask()
{
return (predef | redef);
}
bool isIndex(uint32_t idx)
{
assert(flag_limit != 0); // must be set up already
if (idx < flag_limit)
return (bool)(((predef | redef) >> idx) & 1);
else
return (idx - flag_limit < (uint32_t)overflow_count.length());
}
int &getCount(uint32_t idx)
{
assert(isIndex(idx));
if (idx < flag_limit)
return flag_count[idx];
else
return overflow_count.get(idx - flag_limit);
}
};
bool isRedefined(uint32_t idx)
{
if (idx >= flag_limit)
return false;
return (bool)((redef >> idx) & 1);
}
bool isPredefined(uint32_t idx)
{
if (idx >= flag_limit)
return false;
return (bool)(((predef & ~redef) >> idx) & 1);
}
uint64_t flagIndexMask()
{
return (predef | redef);
}
bool isIndex(uint32_t idx)
{
assert(flag_limit != 0); // must be set up already
if (idx < flag_limit)
return (bool)(((predef | redef) >> idx) & 1);
else
return (idx - flag_limit < (uint32_t)overflow_count.length());
}
int &getCount(uint32_t idx)
{
assert(isIndex(idx));
if (idx < flag_limit)
return flag_count[idx];
else
return overflow_count.get(idx - flag_limit);
}
};
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
// Initialization
void init(read_input_fn_t input_fn = nullptr);
// Resets to a known sane state
void reset();
// Deallocates all storage.
void free();
// Deallocates temporary storage (volatile after next client call).
void free_temps()
{
tsmallbuf.init();
tmallocs.freeAll();
}
// Initialization
void init(read_input_fn_t input_fn = nullptr);
// Resets to a known sane state
void reset();
// Deallocates all storage.
void free();
// Deallocates temporary storage (volatile after next client call).
void free_temps()
{
tsmallbuf.init();
tmallocs.freeAll();
}
// Option management methods
bool set_option(const char *option, const char *value);
const char *get_option(const char *option);
// Option management methods
bool set_option(const char *option, const char *value);
const char *get_option(const char *option);
// Fetching input.
bool ensure_input(int64_t more);
byte *input_scan()
{
return rp;
}
size_t input_remaining()
{
return rplimit - rp;
}
size_t input_consumed()
{
return rp - input.base();
}
// Fetching input.
bool ensure_input(int64_t more);
byte *input_scan()
{
return rp;
}
size_t input_remaining()
{
return rplimit - rp;
}
size_t input_consumed()
{
return rp - input.base();
}
// Entry points to the unpack engine
static int run(int argc, char **argv); // Unix-style entry point.
void check_options();
void start(void *packptr = nullptr, size_t len = 0);
void write_file_to_jar(file *f);
void finish();
// Entry points to the unpack engine
static int run(int argc, char **argv); // Unix-style entry point.
void check_options();
void start(void *packptr = nullptr, size_t len = 0);
void write_file_to_jar(file *f);
void finish();
// Public post unpack methods
int get_files_remaining()
{
return files_remaining;
}
int get_segments_remaining()
{
return archive_next_count;
}
file *get_next_file(); // returns nullptr on last file
// Public post unpack methods
int get_files_remaining()
{
return files_remaining;
}
int get_segments_remaining()
{
return archive_next_count;
}
file *get_next_file(); // returns nullptr on last file
// General purpose methods
void *alloc(size_t size)
{
return alloc_heap(size, true);
}
void *temp_alloc(size_t size)
{
return alloc_heap(size, true, true);
}
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
void saveTo(bytes &b, const char *str)
{
saveTo(b, (byte *)str, strlen(str));
}
void saveTo(bytes &b, bytes &data)
{
saveTo(b, data.ptr, data.len);
}
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
const char *saveStr(const char *str)
{
bytes buf;
saveTo(buf, str);
return buf.strval();
}
const char *saveIntStr(int num)
{
char buf[30];
sprintf(buf, "%d", num);
return saveStr(buf);
}
static unpacker *current(); // find current instance
// General purpose methods
void *alloc(size_t size)
{
return alloc_heap(size, true);
}
void *temp_alloc(size_t size)
{
return alloc_heap(size, true, true);
}
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
void saveTo(bytes &b, const char *str)
{
saveTo(b, (byte *)str, strlen(str));
}
void saveTo(bytes &b, bytes &data)
{
saveTo(b, data.ptr, data.len);
}
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
const char *saveStr(const char *str)
{
bytes buf;
saveTo(buf, str);
return buf.strval();
}
const char *saveIntStr(int num)
{
char buf[30];
sprintf(buf, "%d", num);
return saveStr(buf);
}
static unpacker *current(); // find current instance
// Output management
void set_output(fillbytes *which)
{
assert(wp == nullptr);
which->ensureSize(1 << 12); // covers the average classfile
wpbase = which->base();
wp = which->limit();
wplimit = which->end();
}
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
// Output management
void set_output(fillbytes *which)
{
assert(wp == nullptr);
which->ensureSize(1 << 12); // covers the average classfile
wpbase = which->base();
wp = which->limit();
wplimit = which->end();
}
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
// These take an implicit parameter of wp/wplimit, and resize as necessary:
byte *put_space(size_t len); // allocates space at wp, returns pointer
size_t put_empty(size_t s)
{
byte *p = put_space(s);
return p - wpbase;
}
void ensure_put_space(size_t len);
void put_bytes(bytes &b)
{
b.writeTo(put_space(b.len));
}
void putu1(int n)
{
putu1_at(put_space(1), n);
}
void putu1_fast(int n)
{
putu1_at(wp++, n);
}
void putu2(int n); // { putu2_at(put_space(2), n); }
void putu4(int n); // { putu4_at(put_space(4), n); }
void putu8(int64_t n); // { putu8_at(put_space(8), n); }
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
int putref_index(entry *e, int size); // size in [1..2]
void put_label(int curIP, int size); // size in {2,4}
void putlayout(band **body);
void put_stackmap_type();
// These take an implicit parameter of wp/wplimit, and resize as necessary:
byte *put_space(size_t len); // allocates space at wp, returns pointer
size_t put_empty(size_t s)
{
byte *p = put_space(s);
return p - wpbase;
}
void ensure_put_space(size_t len);
void put_bytes(bytes &b)
{
b.writeTo(put_space(b.len));
}
void putu1(int n)
{
putu1_at(put_space(1), n);
}
void putu1_fast(int n)
{
putu1_at(wp++, n);
}
void putu2(int n); // { putu2_at(put_space(2), n); }
void putu4(int n); // { putu4_at(put_space(4), n); }
void putu8(int64_t n); // { putu8_at(put_space(8), n); }
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
int putref_index(entry *e, int size); // size in [1..2]
void put_label(int curIP, int size); // size in {2,4}
void putlayout(band **body);
void put_stackmap_type();
size_t wpoffset()
{
return (size_t)(wp - wpbase);
} // (unvariant across overflow)
byte *wp_at(size_t offset)
{
return wpbase + offset;
}
uint32_t to_bci(uint32_t bii);
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
band *ref_band_for_op(int bc);
size_t wpoffset()
{
return (size_t)(wp - wpbase);
} // (unvariant across overflow)
byte *wp_at(size_t offset)
{
return wpbase + offset;
}
uint32_t to_bci(uint32_t bii);
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
band *ref_band_for_op(int bc);
// Definitions of standard classfile int formats:
static void putu1_at(byte *wp, int n)
{
assert(n == (n & 0xFF));
wp[0] = n;
}
static void putu2_at(byte *wp, int n);
static void putu4_at(byte *wp, int n);
static void putu8_at(byte *wp, int64_t n);
// Definitions of standard classfile int formats:
static void putu1_at(byte *wp, int n)
{
assert(n == (n & 0xFF));
wp[0] = n;
}
static void putu2_at(byte *wp, int n);
static void putu4_at(byte *wp, int n);
static void putu8_at(byte *wp, int64_t n);
// Private stuff
void reset_cur_classfile();
void write_classfile_tail();
void write_classfile_head();
void write_code();
void write_bc_ops();
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
int write_attrs(int attrc, uint64_t indexBits);
// Private stuff
void reset_cur_classfile();
void write_classfile_tail();
void write_classfile_head();
void write_code();
void write_bc_ops();
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
int write_attrs(int attrc, uint64_t indexBits);
// The readers
void read_bands();
void read_file_header();
void read_cp();
void read_cp_counts(value_stream &hdr);
void read_attr_defs();
void read_ics();
void read_attrs(int attrc, int obj_count);
void read_classes();
void read_code_headers();
void read_bcs();
void read_bc_ops();
void read_files();
void read_Utf8_values(entry *cpMap, int len);
void read_single_words(band &cp_band, entry *cpMap, int len);
void read_double_words(band &cp_bands, entry *cpMap, int len);
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
void read_signature_values(entry *cpMap, int len);
// The readers
void read_bands();
void read_file_header();
void read_cp();
void read_cp_counts(value_stream &hdr);
void read_attr_defs();
void read_ics();
void read_attrs(int attrc, int obj_count);
void read_classes();
void read_code_headers();
void read_bcs();
void read_bc_ops();
void read_files();
void read_Utf8_values(entry *cpMap, int len);
void read_single_words(band &cp_band, entry *cpMap, int len);
void read_double_words(band &cp_bands, entry *cpMap, int len);
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
void read_signature_values(entry *cpMap, int len);
};

View File

@ -45,118 +45,118 @@
// Callback for fetching data, Unix style.
static int64_t read_input_via_stdio(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
{
assert(u->infileptr != nullptr);
assert(minlen <= maxlen); // don't talk nonsense
int64_t numread = 0;
char *bufptr = (char *)buf;
while (numread < minlen)
{
// read available input, up to buf.length or maxlen
int readlen = (1 << 16);
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
int nr = 0;
assert(u->infileptr != nullptr);
assert(minlen <= maxlen); // don't talk nonsense
int64_t numread = 0;
char *bufptr = (char *)buf;
while (numread < minlen)
{
// read available input, up to buf.length or maxlen
int readlen = (1 << 16);
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
int nr = 0;
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
if (nr <= 0)
{
if (errno != EINTR)
break;
nr = 0;
}
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
}
return numread;
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
if (nr <= 0)
{
if (errno != EINTR)
break;
nr = 0;
}
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
}
return numread;
}
enum
{
EOF_MAGIC = 0,
BAD_MAGIC = -1
EOF_MAGIC = 0,
BAD_MAGIC = -1
};
static int read_magic(unpacker *u, char peek[], int peeklen)
{
assert(peeklen == 4); // magic numbers are always 4 bytes
int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
if (nr != peeklen)
{
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
}
int magic = 0;
for (int i = 0; i < peeklen; i++)
{
magic <<= 8;
magic += peek[i] & 0xFF;
}
return magic;
assert(peeklen == 4); // magic numbers are always 4 bytes
int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
if (nr != peeklen)
{
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
}
int magic = 0;
for (int i = 0; i < peeklen; i++)
{
magic <<= 8;
magic += peek[i] & 0xFF;
}
return magic;
}
void unpack_200(FILE *input, FILE *output)
{
unpacker u;
u.init(read_input_via_stdio);
unpacker u;
u.init(read_input_via_stdio);
// initialize jar output
// the output takes ownership of the file handle
jar jarout;
jarout.init(&u);
jarout.jarfp = output;
// initialize jar output
// the output takes ownership of the file handle
jar jarout;
jarout.init(&u);
jarout.jarfp = output;
// the input doesn't
u.infileptr = input;
// the input doesn't
u.infileptr = input;
// read the magic!
char peek[4];
int magic;
magic = read_magic(&u, peek, (int)sizeof(peek));
// read the magic!
char peek[4];
int magic;
magic = read_magic(&u, peek, (int)sizeof(peek));
// if it is a gzip encoded file, we need an extra gzip input filter
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
{
gunzip *gzin = NEW(gunzip, 1);
gzin->init(&u);
// FIXME: why the side effects? WHY?
u.gzin->start(magic);
u.start();
}
else
{
// otherwise, feed the bytes to the unpacker directly
u.start(peek, sizeof(peek));
}
// if it is a gzip encoded file, we need an extra gzip input filter
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
{
gunzip *gzin = NEW(gunzip, 1);
gzin->init(&u);
// FIXME: why the side effects? WHY?
u.gzin->start(magic);
u.start();
}
else
{
// otherwise, feed the bytes to the unpacker directly
u.start(peek, sizeof(peek));
}
// Note: The checks to u.aborting() are necessary to gracefully
// terminate processing when the first segment throws an error.
for (;;)
{
// Each trip through this loop unpacks one segment
// and then resets the unpacker.
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
{
u.write_file_to_jar(filep);
}
// Note: The checks to u.aborting() are necessary to gracefully
// terminate processing when the first segment throws an error.
for (;;)
{
// Each trip through this loop unpacks one segment
// and then resets the unpacker.
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
{
u.write_file_to_jar(filep);
}
// Peek ahead for more data.
magic = read_magic(&u, peek, (int)sizeof(peek));
if (magic != (int)JAVA_PACKAGE_MAGIC)
{
// we do not feel strongly about this kind of thing...
/*
if (magic != EOF_MAGIC)
unpack_abort("garbage after end of pack archive");
*/
break; // all done
}
// Peek ahead for more data.
magic = read_magic(&u, peek, (int)sizeof(peek));
if (magic != (int)JAVA_PACKAGE_MAGIC)
{
// we do not feel strongly about this kind of thing...
/*
if (magic != EOF_MAGIC)
unpack_abort("garbage after end of pack archive");
*/
break; // all done
}
// Release all storage from parsing the old segment.
u.reset();
// Restart, beginning with the peek-ahead.
u.start(peek, sizeof(peek));
}
u.finish();
u.free(); // tidy up malloc blocks
fclose(input);
// Release all storage from parsing the old segment.
u.reset();
// Restart, beginning with the peek-ahead.
u.start(peek, sizeof(peek));
}
u.finish();
u.free(); // tidy up malloc blocks
fclose(input);
}

View File

@ -50,22 +50,22 @@
void *must_malloc(size_t size)
{
size_t msize = size;
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
if (ptr != nullptr)
{
memset(ptr, 0, size);
}
else
{
throw std::runtime_error(ERROR_ENOMEM);
}
return ptr;
size_t msize = size;
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
if (ptr != nullptr)
{
memset(ptr, 0, size);
}
else
{
throw std::runtime_error(ERROR_ENOMEM);
}
return ptr;
}
void unpack_abort(const char *msg)
{
if (msg == nullptr)
msg = "corrupt pack file or internal error";
throw std::runtime_error(msg);
if (msg == nullptr)
msg = "corrupt pack file or internal error";
throw std::runtime_error(msg);
}

View File

@ -35,17 +35,17 @@ void *must_malloc(size_t size);
inline size_t scale_size(size_t size, size_t scale)
{
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
}
inline size_t add_size(size_t size1, size_t size2)
{
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
}
inline size_t add_size(size_t size1, size_t size2, int size3)
{
return add_size(add_size(size1, size2), size3);
return add_size(add_size(size1, size2), size3);
}
struct unpacker;

View File

@ -52,7 +52,7 @@
inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
{
return crc32(c, ptr, len);
return crc32(c, ptr, len);
}
// FIXME: this is bullshit. Do real endianness detection.
@ -68,175 +68,175 @@ inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
void jar::init(unpacker *u_)
{
BYTES_OF(*this).clear();
u = u_;
u->jarout = this;
BYTES_OF(*this).clear();
u = u_;
u->jarout = this;
}
// Write data to the ZIP output stream.
void jar::write_data(void *buff, int len)
{
while (len > 0)
{
int rc = (int)fwrite(buff, 1, len, jarfp);
if (rc <= 0)
{
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
exit(1); // Called only from the native standalone unpacker
}
output_file_offset += rc;
buff = ((char *)buff) + rc;
len -= rc;
}
while (len > 0)
{
int rc = (int)fwrite(buff, 1, len, jarfp);
if (rc <= 0)
{
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
exit(1); // Called only from the native standalone unpacker
}
output_file_offset += rc;
buff = ((char *)buff) + rc;
len -= rc;
}
}
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc)
uint32_t crc)
{
uint32_t fname_length = (uint32_t)strlen(fname);
ushort header[23];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
uint32_t fname_length = (uint32_t)strlen(fname);
ushort header[23];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0201);
header[2] = (ushort)SWAP_BYTES(0xA);
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0201);
header[2] = (ushort)SWAP_BYTES(0xA);
// required version
header[3] = (ushort)SWAP_BYTES(0xA);
// required version
header[3] = (ushort)SWAP_BYTES(0xA);
// flags 02 = maximum sub-compression flag
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
// flags 02 = maximum sub-compression flag
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
// Compression method 8=deflate.
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Compression method 8=deflate.
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Last modified date and time.
header[6] = (ushort)GET_INT_LO(dostime);
header[7] = (ushort)GET_INT_HI(dostime);
// Last modified date and time.
header[6] = (ushort)GET_INT_LO(dostime);
header[7] = (ushort)GET_INT_HI(dostime);
// CRC
header[8] = (ushort)GET_INT_LO(crc);
header[9] = (ushort)GET_INT_HI(crc);
// CRC
header[8] = (ushort)GET_INT_LO(crc);
header[9] = (ushort)GET_INT_HI(crc);
// Compressed length:
header[10] = (ushort)GET_INT_LO(clen);
header[11] = (ushort)GET_INT_HI(clen);
// Compressed length:
header[10] = (ushort)GET_INT_LO(clen);
header[11] = (ushort)GET_INT_HI(clen);
// Uncompressed length.
header[12] = (ushort)GET_INT_LO(len);
header[13] = (ushort)GET_INT_HI(len);
// Uncompressed length.
header[12] = (ushort)GET_INT_LO(len);
header[13] = (ushort)GET_INT_HI(len);
// Filename length
header[14] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[15] = 0;
// So called "comment" length.
header[16] = 0;
// Disk number start
header[17] = 0;
// File flags => binary
header[18] = 0;
// More file flags
header[19] = 0;
header[20] = 0;
// Offset within ZIP file.
header[21] = (ushort)GET_INT_LO(output_file_offset);
header[22] = (ushort)GET_INT_HI(output_file_offset);
// Filename length
header[14] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[15] = 0;
// So called "comment" length.
header[16] = 0;
// Disk number start
header[17] = 0;
// File flags => binary
header[18] = 0;
// More file flags
header[19] = 0;
header[20] = 0;
// Offset within ZIP file.
header[21] = (ushort)GET_INT_LO(output_file_offset);
header[22] = (ushort)GET_INT_HI(output_file_offset);
// Copy the whole thing into the central directory.
central_directory.append(header, sizeof(header));
// Copy the whole thing into the central directory.
central_directory.append(header, sizeof(header));
// Copy the fname to the header.
central_directory.append(fname, fname_length);
// Copy the fname to the header.
central_directory.append(fname, fname_length);
central_directory_count++;
central_directory_count++;
}
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc)
uint32_t crc)
{
uint32_t fname_length = (uint32_t)strlen(fname);
ushort header[15];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
uint32_t fname_length = (uint32_t)strlen(fname);
ushort header[15];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
// ZIP LOC magic.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0403);
// ZIP LOC magic.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0403);
// Version
header[2] = (ushort)SWAP_BYTES(0xA);
// Version
header[2] = (ushort)SWAP_BYTES(0xA);
// flags 02 = maximum sub-compression flag
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
// flags 02 = maximum sub-compression flag
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
// Compression method = deflate
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Compression method = deflate
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Last modified date and time.
header[5] = (ushort)GET_INT_LO(dostime);
header[6] = (ushort)GET_INT_HI(dostime);
// Last modified date and time.
header[5] = (ushort)GET_INT_LO(dostime);
header[6] = (ushort)GET_INT_HI(dostime);
// CRC
header[7] = (ushort)GET_INT_LO(crc);
header[8] = (ushort)GET_INT_HI(crc);
// CRC
header[7] = (ushort)GET_INT_LO(crc);
header[8] = (ushort)GET_INT_HI(crc);
// Compressed length:
header[9] = (ushort)GET_INT_LO(clen);
header[10] = (ushort)GET_INT_HI(clen);
// Compressed length:
header[9] = (ushort)GET_INT_LO(clen);
header[10] = (ushort)GET_INT_HI(clen);
// Uncompressed length.
header[11] = (ushort)GET_INT_LO(len);
header[12] = (ushort)GET_INT_HI(len);
// Uncompressed length.
header[11] = (ushort)GET_INT_LO(len);
header[12] = (ushort)GET_INT_HI(len);
// Filename length
header[13] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[14] = 0;
// Filename length
header[13] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[14] = 0;
// Write the LOC header to the output file.
write_data(header, (int)sizeof(header));
// Write the LOC header to the output file.
write_data(header, (int)sizeof(header));
// Copy the fname to the header.
write_data((char *)fname, (int)fname_length);
// Copy the fname to the header.
write_data((char *)fname, (int)fname_length);
}
void jar::write_central_directory()
{
bytes mc;
mc.set("PACK200");
bytes mc;
mc.set("PACK200");
ushort header[11];
ushort header[11];
// Create the End of Central Directory structure.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0605);
// disk numbers
header[2] = 0;
header[3] = 0;
// Number of entries in central directory.
header[4] = (ushort)SWAP_BYTES(central_directory_count);
header[5] = (ushort)SWAP_BYTES(central_directory_count);
// Size of the central directory}
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
// Offset of central directory within disk.
header[8] = (ushort)GET_INT_LO(output_file_offset);
header[9] = (ushort)GET_INT_HI(output_file_offset);
// zipfile comment length;
header[10] = (ushort)SWAP_BYTES((int)mc.len);
// Create the End of Central Directory structure.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0605);
// disk numbers
header[2] = 0;
header[3] = 0;
// Number of entries in central directory.
header[4] = (ushort)SWAP_BYTES(central_directory_count);
header[5] = (ushort)SWAP_BYTES(central_directory_count);
// Size of the central directory}
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
// Offset of central directory within disk.
header[8] = (ushort)GET_INT_LO(output_file_offset);
header[9] = (ushort)GET_INT_HI(output_file_offset);
// zipfile comment length;
header[10] = (ushort)SWAP_BYTES((int)mc.len);
// Write the central directory.
write_data(central_directory.b);
// Write the central directory.
write_data(central_directory.b);
// Write the End of Central Directory structure.
write_data(header, (int)sizeof(header));
// Write the End of Central Directory structure.
write_data(header, (int)sizeof(header));
// Write the comment.
write_data(mc);
// Write the comment.
write_data(mc);
}
// Public API
@ -244,74 +244,74 @@ void jar::write_central_directory()
// Open a Jar file and initialize.
void jar::openJarFile(const char *fname)
{
if (!jarfp)
{
jarfp = fopen(fname, "wb");
if (!jarfp)
{
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
exit(3); // Called only from the native standalone unpacker
}
}
if (!jarfp)
{
jarfp = fopen(fname, "wb");
if (!jarfp)
{
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
exit(3); // Called only from the native standalone unpacker
}
}
}
// Add a ZIP entry and copy the file data
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
bytes &tail)
bytes &tail)
{
int len = (int)(head.len + tail.len);
int clen = 0;
int len = (int)(head.len + tail.len);
int clen = 0;
uint32_t crc = get_crc32(0, Z_NULL, 0);
if (head.len != 0)
crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
if (tail.len != 0)
crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
uint32_t crc = get_crc32(0, Z_NULL, 0);
if (head.len != 0)
crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
if (tail.len != 0)
crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
bool deflate = (deflate_hint && len > 0);
bool deflate = (deflate_hint && len > 0);
if (deflate)
{
if (deflate_bytes(head, tail) == false)
{
deflate = false;
}
}
clen = (int)((deflate) ? deflated.size() : len);
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
write_jar_header(fname, !deflate, modtime, len, clen, crc);
if (deflate)
{
if (deflate_bytes(head, tail) == false)
{
deflate = false;
}
}
clen = (int)((deflate) ? deflated.size() : len);
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
write_jar_header(fname, !deflate, modtime, len, clen, crc);
if (deflate)
{
write_data(deflated.b);
}
else
{
write_data(head);
write_data(tail);
}
if (deflate)
{
write_data(deflated.b);
}
else
{
write_data(head);
write_data(tail);
}
}
// Add a ZIP entry for a directory name no data
void jar::addDirectoryToJarFile(const char *dir_name)
{
bool store = true;
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
bool store = true;
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
}
// Write out the central directory and close the jar file.
void jar::closeJarFile(bool central)
{
if (jarfp)
{
fflush(jarfp);
if (central)
write_central_directory();
fflush(jarfp);
fclose(jarfp);
}
reset();
if (jarfp)
{
fflush(jarfp);
if (central)
write_central_directory();
fflush(jarfp);
fclose(jarfp);
}
reset();
}
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
@ -320,9 +320,9 @@ void jar::closeJarFile(bool central)
*/
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
{
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
}
/*
#ifdef _REENTRANT // solaris
@ -336,20 +336,20 @@ extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
*/
uint32_t jar::get_dostime(int modtime)
{
// see defines.h
if (modtime != 0 && modtime == modtime_cache)
return dostime_cache;
if (modtime != 0 && default_modtime == 0)
default_modtime = modtime; // catch a reasonable default
time_t t = modtime;
struct tm sbuf;
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
struct tm *s = gmtime_r(&t, &sbuf);
modtime_cache = modtime;
dostime_cache =
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
return dostime_cache;
// see defines.h
if (modtime != 0 && modtime == modtime_cache)
return dostime_cache;
if (modtime != 0 && default_modtime == 0)
default_modtime = modtime; // catch a reasonable default
time_t t = modtime;
struct tm sbuf;
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
struct tm *s = gmtime_r(&t, &sbuf);
modtime_cache = modtime;
dostime_cache =
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
return dostime_cache;
}
/* Returns true on success, and will set the clen to the compressed
@ -358,232 +358,232 @@ uint32_t jar::get_dostime(int modtime)
*/
bool jar::deflate_bytes(bytes &head, bytes &tail)
{
int len = (int)(head.len + tail.len);
int len = (int)(head.len + tail.len);
z_stream zs;
BYTES_OF(zs).clear();
z_stream zs;
BYTES_OF(zs).clear();
// NOTE: the window size should always be -MAX_WBITS normally -15.
// unzip/zipup.c and java/Deflater.c
// NOTE: the window size should always be -MAX_WBITS normally -15.
// unzip/zipup.c and java/Deflater.c
int error =
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
if (error != Z_OK)
{
/*
switch (error)
{
case Z_MEM_ERROR:
PRINTCR((2, "Error: deflate error : Out of memory \n"));
break;
case Z_STREAM_ERROR:
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
break;
case Z_VERSION_ERROR:
PRINTCR((2, "Error: deflate error : Invalid version\n"));
break;
default:
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
}
*/
return false;
}
int error =
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
if (error != Z_OK)
{
/*
switch (error)
{
case Z_MEM_ERROR:
PRINTCR((2, "Error: deflate error : Out of memory \n"));
break;
case Z_STREAM_ERROR:
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
break;
case Z_VERSION_ERROR:
PRINTCR((2, "Error: deflate error : Invalid version\n"));
break;
default:
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
}
*/
return false;
}
deflated.empty();
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
zs.avail_out = (int)deflated.size();
deflated.empty();
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
zs.avail_out = (int)deflated.size();
zs.next_in = (uchar *)head.ptr;
zs.avail_in = (int)head.len;
zs.next_in = (uchar *)head.ptr;
zs.avail_in = (int)head.len;
bytes *first = &head;
bytes *last = &tail;
if (last->len == 0)
{
first = nullptr;
last = &head;
}
else if (first->len == 0)
{
first = nullptr;
}
bytes *first = &head;
bytes *last = &tail;
if (last->len == 0)
{
first = nullptr;
last = &head;
}
else if (first->len == 0)
{
first = nullptr;
}
if (first != nullptr && error == Z_OK)
{
zs.next_in = (uchar *)first->ptr;
zs.avail_in = (int)first->len;
error = deflate(&zs, Z_NO_FLUSH);
}
if (error == Z_OK)
{
zs.next_in = (uchar *)last->ptr;
zs.avail_in = (int)last->len;
error = deflate(&zs, Z_FINISH);
}
if (error == Z_STREAM_END)
{
if (len > (int)zs.total_out)
{
deflated.b.len = zs.total_out;
deflateEnd(&zs);
return true;
}
deflateEnd(&zs);
return false;
}
if (first != nullptr && error == Z_OK)
{
zs.next_in = (uchar *)first->ptr;
zs.avail_in = (int)first->len;
error = deflate(&zs, Z_NO_FLUSH);
}
if (error == Z_OK)
{
zs.next_in = (uchar *)last->ptr;
zs.avail_in = (int)last->len;
error = deflate(&zs, Z_FINISH);
}
if (error == Z_STREAM_END)
{
if (len > (int)zs.total_out)
{
deflated.b.len = zs.total_out;
deflateEnd(&zs);
return true;
}
deflateEnd(&zs);
return false;
}
deflateEnd(&zs);
return false;
deflateEnd(&zs);
return false;
}
// Callback for fetching data from a GZIP input stream
static int64_t read_input_via_gzip(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
{
assert(minlen <= maxlen); // don't talk nonsense
int64_t numread = 0;
char *bufptr = (char *)buf;
char *inbuf = u->gzin->inbuf;
size_t inbuflen = sizeof(u->gzin->inbuf);
unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
z_stream &zs = *(z_stream *)u->gzin->zstream;
while (numread < minlen)
{
int readlen = (1 << 16); // pretty arbitrary
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
zs.next_out = (uchar *)bufptr;
zs.avail_out = readlen;
if (zs.avail_in == 0)
{
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.next_in = (uchar *)inbuf;
}
int error = inflate(&zs, Z_NO_FLUSH);
if (error != Z_OK && error != Z_STREAM_END)
{
unpack_abort("error inflating input");
break;
}
int nr = readlen - zs.avail_out;
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
if (error == Z_STREAM_END)
{
enum
{
TRAILER_LEN = 8
};
// skip 8-byte trailer
if (zs.avail_in >= TRAILER_LEN)
{
zs.avail_in -= TRAILER_LEN;
}
else
{
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
// any extraneous data, as we dont support concatenated .gz
// files just yet.
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.avail_in += extra - TRAILER_LEN;
}
// %%% should check final CRC and length here
// %%% should check for concatenated *.gz files here
if (zs.avail_in > 0)
unpack_abort("garbage after end of deflated input stream");
// pop this filter off:
u->gzin->free();
break;
}
}
assert(minlen <= maxlen); // don't talk nonsense
int64_t numread = 0;
char *bufptr = (char *)buf;
char *inbuf = u->gzin->inbuf;
size_t inbuflen = sizeof(u->gzin->inbuf);
unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
z_stream &zs = *(z_stream *)u->gzin->zstream;
while (numread < minlen)
{
int readlen = (1 << 16); // pretty arbitrary
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
zs.next_out = (uchar *)bufptr;
zs.avail_out = readlen;
if (zs.avail_in == 0)
{
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.next_in = (uchar *)inbuf;
}
int error = inflate(&zs, Z_NO_FLUSH);
if (error != Z_OK && error != Z_STREAM_END)
{
unpack_abort("error inflating input");
break;
}
int nr = readlen - zs.avail_out;
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
if (error == Z_STREAM_END)
{
enum
{
TRAILER_LEN = 8
};
// skip 8-byte trailer
if (zs.avail_in >= TRAILER_LEN)
{
zs.avail_in -= TRAILER_LEN;
}
else
{
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
// any extraneous data, as we dont support concatenated .gz
// files just yet.
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.avail_in += extra - TRAILER_LEN;
}
// %%% should check final CRC and length here
// %%% should check for concatenated *.gz files here
if (zs.avail_in > 0)
unpack_abort("garbage after end of deflated input stream");
// pop this filter off:
u->gzin->free();
break;
}
}
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
// (int)minlen, (int)maxlen, (int)numread);
return numread;
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
// (int)minlen, (int)maxlen, (int)numread);
return numread;
}
void gunzip::init(unpacker *u_)
{
BYTES_OF(*this).clear();
u = u_;
assert(u->gzin == nullptr); // once only, please
read_input_fn = (void *)u->read_input_fn;
zstream = NEW(z_stream, 1);
u->gzin = this;
u->read_input_fn = read_input_via_gzip;
BYTES_OF(*this).clear();
u = u_;
assert(u->gzin == nullptr); // once only, please
read_input_fn = (void *)u->read_input_fn;
zstream = NEW(z_stream, 1);
u->gzin = this;
u->read_input_fn = read_input_via_gzip;
}
void gunzip::start(int magic)
{
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
enum
{
FHCRC = (1 << 1),
FEXTRA = (1 << 2),
FNAME = (1 << 3),
FCOMMENT = (1 << 4)
};
char gz_mtime[4];
char gz_xfl[1];
char gz_os[1];
char gz_extra_len[2];
char gz_hcrc[2];
char gz_ignore;
// do not save extra, name, comment
read_fixed_field(gz_mtime, sizeof(gz_mtime));
read_fixed_field(gz_xfl, sizeof(gz_xfl));
read_fixed_field(gz_os, sizeof(gz_os));
if (gz_flg & FEXTRA)
{
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
int extra_len = gz_extra_len[0] & 0xFF;
extra_len += (gz_extra_len[1] & 0xFF) << 8;
for (; extra_len > 0; extra_len--)
{
read_fixed_field(&gz_ignore, 1);
}
}
int null_terms = 0;
if (gz_flg & FNAME)
null_terms++;
if (gz_flg & FCOMMENT)
null_terms++;
for (; null_terms; null_terms--)
{
for (;;)
{
gz_ignore = 0;
read_fixed_field(&gz_ignore, 1);
if (gz_ignore == 0)
break;
}
}
if (gz_flg & FHCRC)
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
enum
{
FHCRC = (1 << 1),
FEXTRA = (1 << 2),
FNAME = (1 << 3),
FCOMMENT = (1 << 4)
};
char gz_mtime[4];
char gz_xfl[1];
char gz_os[1];
char gz_extra_len[2];
char gz_hcrc[2];
char gz_ignore;
// do not save extra, name, comment
read_fixed_field(gz_mtime, sizeof(gz_mtime));
read_fixed_field(gz_xfl, sizeof(gz_xfl));
read_fixed_field(gz_os, sizeof(gz_os));
if (gz_flg & FEXTRA)
{
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
int extra_len = gz_extra_len[0] & 0xFF;
extra_len += (gz_extra_len[1] & 0xFF) << 8;
for (; extra_len > 0; extra_len--)
{
read_fixed_field(&gz_ignore, 1);
}
}
int null_terms = 0;
if (gz_flg & FNAME)
null_terms++;
if (gz_flg & FCOMMENT)
null_terms++;
for (; null_terms; null_terms--)
{
for (;;)
{
gz_ignore = 0;
read_fixed_field(&gz_ignore, 1);
if (gz_ignore == 0)
break;
}
}
if (gz_flg & FHCRC)
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
// now the input stream is ready to read into the inflater
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
if (error != Z_OK)
{
unpack_abort("cannot create input");
}
// now the input stream is ready to read into the inflater
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
if (error != Z_OK)
{
unpack_abort("cannot create input");
}
}
void gunzip::free()
{
assert(u->gzin == this);
u->gzin = nullptr;
u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
inflateEnd((z_stream *)zstream);
::free(zstream);
zstream = nullptr;
::free(this);
assert(u->gzin == this);
u->gzin = nullptr;
u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
inflateEnd((z_stream *)zstream);
::free(zstream);
zstream = nullptr;
::free(this);
}
void gunzip::read_fixed_field(char *buf, size_t buflen)
{
int64_t nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
if ((size_t)nr != buflen)
unpack_abort("short stream header");
int64_t nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
if ((size_t)nr != buflen)
unpack_abort("short stream header");
}

View File

@ -31,80 +31,80 @@ struct unpacker;
struct jar
{
// JAR file writer
FILE *jarfp;
int default_modtime;
// JAR file writer
FILE *jarfp;
int default_modtime;
// Used by unix2dostime:
int modtime_cache;
uint32_t dostime_cache;
// Used by unix2dostime:
int modtime_cache;
uint32_t dostime_cache;
// Private members
fillbytes central_directory;
ushort central_directory_count;
uint32_t output_file_offset;
fillbytes deflated; // temporary buffer
// Private members
fillbytes central_directory;
ushort central_directory_count;
uint32_t output_file_offset;
fillbytes deflated; // temporary buffer
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// Public Methods
void openJarFile(const char *fname);
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
bytes &tail);
void addDirectoryToJarFile(const char *dir_name);
void closeJarFile(bool central);
// Public Methods
void openJarFile(const char *fname);
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
bytes &tail);
void addDirectoryToJarFile(const char *dir_name);
void closeJarFile(bool central);
void init(unpacker *u_);
void init(unpacker *u_);
void free()
{
central_directory.free();
deflated.free();
}
void free()
{
central_directory.free();
deflated.free();
}
void reset()
{
free();
init(u);
}
void reset()
{
free();
init(u);
}
// Private Methods
void write_data(void *ptr, int len);
void write_data(bytes &b)
{
write_data(b.ptr, (int)b.len);
}
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc);
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
unsigned int crc);
void write_central_directory();
uint32_t dostime(int y, int n, int d, int h, int m, int s);
uint32_t get_dostime(int modtime);
// Private Methods
void write_data(void *ptr, int len);
void write_data(bytes &b)
{
write_data(b.ptr, (int)b.len);
}
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc);
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
unsigned int crc);
void write_central_directory();
uint32_t dostime(int y, int n, int d, int h, int m, int s);
uint32_t get_dostime(int modtime);
// The definitions of these depend on the NO_ZLIB option:
bool deflate_bytes(bytes &head, bytes &tail);
static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
// The definitions of these depend on the NO_ZLIB option:
bool deflate_bytes(bytes &head, bytes &tail);
static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
};
struct gunzip
{
// optional gzip input stream control block
// optional gzip input stream control block
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// pointer to outer unpacker, for error checks etc.
unpacker *u;
void *read_input_fn; // underlying \bchar\b stream
void *zstream; // inflater state
char inbuf[1 << 14]; // input buffer
void *read_input_fn; // underlying \bchar\b stream
void *zstream; // inflater state
char inbuf[1 << 14]; // input buffer
void init(unpacker *u_); // pushes new value on u->read_input_fn
void init(unpacker *u_); // pushes new value on u->read_input_fn
void free();
void free();
void start(int magic);
void start(int magic);
// private stuff
void read_fixed_field(char *buf, size_t buflen);
// private stuff
void read_fixed_field(char *buf, size_t buflen);
};