Compression algo dependencies, still need hackery...
This commit is contained in:
43
depends/pack200/CMakeLists.txt
Normal file
43
depends/pack200/CMakeLists.txt
Normal file
@ -0,0 +1,43 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
project(unpack200)
|
||||
|
||||
# Find ZLIB for quazip
|
||||
# Use system zlib on unix and Qt ZLIB on Windows
|
||||
IF(UNIX)
|
||||
find_package(ZLIB REQUIRED)
|
||||
ELSE(UNIX)
|
||||
get_filename_component (ZLIB_FOUND_DIR "${Qt5Core_DIR}/../../../include/QtZlib" ABSOLUTE)
|
||||
SET(ZLIB_INCLUDE_DIRS ${ZLIB_FOUND_DIR} CACHE PATH "Path to ZLIB headers of Qt")
|
||||
SET(ZLIB_LIBRARIES "")
|
||||
IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
MESSAGE("Please specify a valid zlib include dir")
|
||||
ENDIF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(PACK200_SRC
|
||||
src/bands.cpp
|
||||
src/bands.h
|
||||
src/bytes.cpp
|
||||
src/bytes.h
|
||||
src/coding.cpp
|
||||
src/coding.h
|
||||
src/constants.h
|
||||
src/defines.h
|
||||
src/main.cpp
|
||||
src/unpack.cpp
|
||||
src/unpack.h
|
||||
src/utils.cpp
|
||||
src/utils.h
|
||||
src/zip.cpp
|
||||
src/zip.h
|
||||
)
|
||||
|
||||
add_executable(unpack200 ${PACK200_SRC})
|
||||
|
||||
IF(UNIX)
|
||||
target_link_libraries(unpack200 ${ZLIB_LIBRARIES})
|
||||
ELSE()
|
||||
# zlib is part of Qt on windows. use it.
|
||||
QT5_USE_MODULES(unpack200 Core)
|
||||
ENDIF()
|
1
depends/pack200/include/unpack200.h
Normal file
1
depends/pack200/include/unpack200.h
Normal file
@ -0,0 +1 @@
|
||||
|
451
depends/pack200/src/bands.cpp
Normal file
451
depends/pack200/src/bands.cpp
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
// Small program for unpacking specially compressed Java packages.
|
||||
// John R. Rose
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
inline void band::abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
inline bool band::aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
||||
|
||||
void band::readData(int expectedLength)
|
||||
{
|
||||
CHECK;
|
||||
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);
|
||||
|
||||
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)
|
||||
jlong generous = (jlong)length * (B_MAX * 3 + 1) + C_SLOP;
|
||||
u->ensure_input(generous);
|
||||
}
|
||||
|
||||
// Read one value to see what it might be.
|
||||
int XB = _meta_default;
|
||||
int cp1 = 0, cp2 = 0;
|
||||
if (!is_BYTE1)
|
||||
{
|
||||
// must be a variable-length coding
|
||||
assert(defc->B() > 1 && defc->L() > 0);
|
||||
// must have already read from previous band:
|
||||
assert(bn >= BAND_LIMIT || bn <= 0 || bn == e_cp_Utf8_big_chars ||
|
||||
endsWith(name, "_lo") // preceded by _hi conditional band
|
||||
||
|
||||
bn == e_file_options // preceded by conditional band
|
||||
||
|
||||
u->rp == u->all_bands[bn - 1].maxRP() || u->all_bands[bn - 1].defc == nullptr);
|
||||
|
||||
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);
|
||||
CHECK;
|
||||
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;
|
||||
cp1 = 1;
|
||||
}
|
||||
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);
|
||||
CHECK;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
void band::setIndex(cpindex *ix_)
|
||||
{
|
||||
assert(ix_ == nullptr || ixTag == ix_->ixTag);
|
||||
ix = ix_;
|
||||
}
|
||||
void band::setIndexByTag(byte tag)
|
||||
{
|
||||
setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
|
||||
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
|
||||
{
|
||||
CHECK_0;
|
||||
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))
|
||||
abort(n == -1 ? "nullptr ref" : "bad ref");
|
||||
return ref;
|
||||
}
|
||||
|
||||
jlong band::getLong(band &lo_band, bool have_hi)
|
||||
{
|
||||
band &hi_band = (*this);
|
||||
assert(lo_band.bn == hi_band.bn + 1);
|
||||
uint lo = lo_band.getInt();
|
||||
if (!have_hi)
|
||||
{
|
||||
assert(hi_band.length == 0);
|
||||
return makeLong(0, lo);
|
||||
}
|
||||
uint hi = hi_band.getInt();
|
||||
return makeLong(hi, lo);
|
||||
}
|
||||
|
||||
int band::getIntTotal()
|
||||
{
|
||||
CHECK_0;
|
||||
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)
|
||||
{
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
for (int k = length - 1; k > 0; k--)
|
||||
{
|
||||
int prev_total = total;
|
||||
total += vs[0].getInt();
|
||||
if (total < prev_total)
|
||||
{
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rewind();
|
||||
total_memo = total + 1;
|
||||
return total;
|
||||
}
|
||||
|
||||
int band::getIntCount(int tag)
|
||||
{
|
||||
CHECK_0;
|
||||
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);
|
||||
CHECK_0;
|
||||
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)
|
||||
|
||||
#define INDEX(tag) INDEX_INIT(tag, 0, 0)
|
||||
#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0)
|
||||
#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1)
|
||||
#define NO_INDEX 0
|
||||
|
||||
struct band_init
|
||||
{
|
||||
int defc;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define BAND_INIT(name, 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}};
|
||||
#define NUM_BAND_INITS (sizeof(all_band_inits) / sizeof(all_band_inits[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);
|
||||
assert(bi.bn == i); // band array consistent w/ band enum
|
||||
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];
|
||||
uint tag = scan->ixTag; // Cf. #define INDEX(tag) above
|
||||
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
|
||||
{
|
||||
scan->setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
}
|
||||
}
|
492
depends/pack200/src/bands.h
Normal file
492
depends/pack200/src/bands.h
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
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 setIndex(cpindex *ix_);
|
||||
void setIndexByTag(byte tag);
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
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);
|
||||
jlong getLong(band &lo_band, bool have_hi);
|
||||
|
||||
static jlong makeLong(uint hi, uint lo)
|
||||
{
|
||||
return ((julong)hi << 32) + (((julong)lo << 32) >> 32);
|
||||
}
|
||||
|
||||
int getIntTotal();
|
||||
int getIntCount(int tag);
|
||||
|
||||
static band *makeBands(unpacker *u);
|
||||
static void initIndexes(unpacker *u);
|
||||
|
||||
void abort(const char *msg = nullptr); //{ u->abort(msg); }
|
||||
bool aborting(); //{ return u->aborting(); }
|
||||
};
|
||||
|
||||
extern band all_bands[];
|
||||
|
||||
#define BAND_LOCAL /* \
|
||||
band* band_temp = all_bands; \
|
||||
band* all_bands = band_temp */
|
||||
|
||||
// Band schema:
|
||||
enum band_number
|
||||
{
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// bc_invokeinit family:
|
||||
e_bc_initref,
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
// Symbolic names for bands, as if in a giant global struct:
|
||||
//#define archive_magic all_bands[e_archive_magic]
|
||||
//#define archive_header all_bands[e_archive_header]
|
||||
//#define band_headers all_bands[e_band_headers]
|
||||
#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix]
|
||||
#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix]
|
||||
#define cp_Utf8_chars all_bands[e_cp_Utf8_chars]
|
||||
#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix]
|
||||
#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars]
|
||||
#define cp_Int all_bands[e_cp_Int]
|
||||
#define cp_Float all_bands[e_cp_Float]
|
||||
#define cp_Long_hi all_bands[e_cp_Long_hi]
|
||||
#define cp_Long_lo all_bands[e_cp_Long_lo]
|
||||
#define cp_Double_hi all_bands[e_cp_Double_hi]
|
||||
#define cp_Double_lo all_bands[e_cp_Double_lo]
|
||||
#define cp_String all_bands[e_cp_String]
|
||||
#define cp_Class all_bands[e_cp_Class]
|
||||
#define cp_Signature_form all_bands[e_cp_Signature_form]
|
||||
#define cp_Signature_classes all_bands[e_cp_Signature_classes]
|
||||
#define cp_Descr_name all_bands[e_cp_Descr_name]
|
||||
#define cp_Descr_type all_bands[e_cp_Descr_type]
|
||||
#define cp_Field_class all_bands[e_cp_Field_class]
|
||||
#define cp_Field_desc all_bands[e_cp_Field_desc]
|
||||
#define cp_Method_class all_bands[e_cp_Method_class]
|
||||
#define cp_Method_desc all_bands[e_cp_Method_desc]
|
||||
#define cp_Imethod_class all_bands[e_cp_Imethod_class]
|
||||
#define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
|
||||
#define attr_definition_headers all_bands[e_attr_definition_headers]
|
||||
#define attr_definition_name all_bands[e_attr_definition_name]
|
||||
#define attr_definition_layout all_bands[e_attr_definition_layout]
|
||||
#define ic_this_class all_bands[e_ic_this_class]
|
||||
#define ic_flags all_bands[e_ic_flags]
|
||||
#define ic_outer_class all_bands[e_ic_outer_class]
|
||||
#define ic_name all_bands[e_ic_name]
|
||||
#define class_this all_bands[e_class_this]
|
||||
#define class_super all_bands[e_class_super]
|
||||
#define class_interface_count all_bands[e_class_interface_count]
|
||||
#define class_interface all_bands[e_class_interface]
|
||||
#define class_field_count all_bands[e_class_field_count]
|
||||
#define class_method_count all_bands[e_class_method_count]
|
||||
#define field_descr all_bands[e_field_descr]
|
||||
#define field_flags_hi all_bands[e_field_flags_hi]
|
||||
#define field_flags_lo all_bands[e_field_flags_lo]
|
||||
#define field_attr_count all_bands[e_field_attr_count]
|
||||
#define field_attr_indexes all_bands[e_field_attr_indexes]
|
||||
#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ]
|
||||
#define field_Signature_RS all_bands[e_field_Signature_RS]
|
||||
#define field_attr_bands all_bands[e_field_attr_bands]
|
||||
#define method_descr all_bands[e_method_descr]
|
||||
#define method_flags_hi all_bands[e_method_flags_hi]
|
||||
#define method_flags_lo all_bands[e_method_flags_lo]
|
||||
#define method_attr_count all_bands[e_method_attr_count]
|
||||
#define method_attr_indexes all_bands[e_method_attr_indexes]
|
||||
#define method_Exceptions_N all_bands[e_method_Exceptions_N]
|
||||
#define method_Exceptions_RC all_bands[e_method_Exceptions_RC]
|
||||
#define method_Signature_RS all_bands[e_method_Signature_RS]
|
||||
#define method_attr_bands all_bands[e_method_attr_bands]
|
||||
#define class_flags_hi all_bands[e_class_flags_hi]
|
||||
#define class_flags_lo all_bands[e_class_flags_lo]
|
||||
#define class_attr_count all_bands[e_class_attr_count]
|
||||
#define class_attr_indexes all_bands[e_class_attr_indexes]
|
||||
#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN]
|
||||
#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC]
|
||||
#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN]
|
||||
#define class_Signature_RS all_bands[e_class_Signature_RS]
|
||||
#define class_InnerClasses_N all_bands[e_class_InnerClasses_N]
|
||||
#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC]
|
||||
#define class_InnerClasses_F all_bands[e_class_InnerClasses_F]
|
||||
#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN]
|
||||
#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN]
|
||||
#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H]
|
||||
#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H]
|
||||
#define class_attr_bands all_bands[e_class_attr_bands]
|
||||
#define code_headers all_bands[e_code_headers]
|
||||
#define code_max_stack all_bands[e_code_max_stack]
|
||||
#define code_max_na_locals all_bands[e_code_max_na_locals]
|
||||
#define code_handler_count all_bands[e_code_handler_count]
|
||||
#define code_handler_start_P all_bands[e_code_handler_start_P]
|
||||
#define code_handler_end_PO all_bands[e_code_handler_end_PO]
|
||||
#define code_handler_catch_PO all_bands[e_code_handler_catch_PO]
|
||||
#define code_handler_class_RCN all_bands[e_code_handler_class_RCN]
|
||||
#define code_flags_hi all_bands[e_code_flags_hi]
|
||||
#define code_flags_lo all_bands[e_code_flags_lo]
|
||||
#define code_attr_count all_bands[e_code_attr_count]
|
||||
#define code_attr_indexes all_bands[e_code_attr_indexes]
|
||||
#define code_StackMapTable_N all_bands[e_code_StackMapTable_N]
|
||||
#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T]
|
||||
#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N]
|
||||
#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N]
|
||||
#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset]
|
||||
#define code_StackMapTable_T all_bands[e_code_StackMapTable_T]
|
||||
#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC]
|
||||
#define code_StackMapTable_P all_bands[e_code_StackMapTable_P]
|
||||
#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N]
|
||||
#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P]
|
||||
#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line]
|
||||
#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N]
|
||||
#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P]
|
||||
#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O]
|
||||
#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU]
|
||||
#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS]
|
||||
#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot]
|
||||
#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N]
|
||||
#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P]
|
||||
#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O]
|
||||
#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU]
|
||||
#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS]
|
||||
#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot]
|
||||
#define code_attr_bands all_bands[e_code_attr_bands]
|
||||
#define bc_codes all_bands[e_bc_codes]
|
||||
#define bc_case_count all_bands[e_bc_case_count]
|
||||
#define bc_case_value all_bands[e_bc_case_value]
|
||||
#define bc_byte all_bands[e_bc_byte]
|
||||
#define bc_short all_bands[e_bc_short]
|
||||
#define bc_local all_bands[e_bc_local]
|
||||
#define bc_label all_bands[e_bc_label]
|
||||
#define bc_intref all_bands[e_bc_intref]
|
||||
#define bc_floatref all_bands[e_bc_floatref]
|
||||
#define bc_longref all_bands[e_bc_longref]
|
||||
#define bc_doubleref all_bands[e_bc_doubleref]
|
||||
#define bc_stringref all_bands[e_bc_stringref]
|
||||
#define bc_classref all_bands[e_bc_classref]
|
||||
#define bc_fieldref all_bands[e_bc_fieldref]
|
||||
#define bc_methodref all_bands[e_bc_methodref]
|
||||
#define bc_imethodref all_bands[e_bc_imethodref]
|
||||
#define bc_thisfield all_bands[e_bc_thisfield]
|
||||
#define bc_superfield all_bands[e_bc_superfield]
|
||||
#define bc_thismethod all_bands[e_bc_thismethod]
|
||||
#define bc_supermethod all_bands[e_bc_supermethod]
|
||||
#define bc_initref all_bands[e_bc_initref]
|
||||
#define bc_escref all_bands[e_bc_escref]
|
||||
#define bc_escrefsize all_bands[e_bc_escrefsize]
|
||||
#define bc_escsize all_bands[e_bc_escsize]
|
||||
#define bc_escbyte all_bands[e_bc_escbyte]
|
||||
#define file_name all_bands[e_file_name]
|
||||
#define file_size_hi all_bands[e_file_size_hi]
|
||||
#define file_size_lo all_bands[e_file_size_lo]
|
||||
#define file_modtime all_bands[e_file_modtime]
|
||||
#define file_options all_bands[e_file_options]
|
217
depends/pack200/src/bytes.cpp
Normal file
217
depends/pack200/src/bytes.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
static byte dummy[1 << 10];
|
||||
|
||||
bool bytes::inBounds(const void *p)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::free()
|
||||
{
|
||||
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 *bytes::writeTo(byte *bp)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void bytes::saveFrom(const void *ptr_, size_t len_)
|
||||
{
|
||||
malloc(len_);
|
||||
// Save as much as possible. (Helps unpacker::abort.)
|
||||
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_);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
assert(unpack_aborting());
|
||||
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
|
||||
}
|
||||
|
||||
int ptrlist::indexOf(const void *x)
|
||||
{
|
||||
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 intlist::indexOf(int x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
284
depends/pack200/src/bytes.h
Normal file
284
depends/pack200/src/bytes.h
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct bytes
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
|
||||
|
||||
struct fillbytes
|
||||
{
|
||||
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(uint 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
|
||||
}
|
||||
|
||||
// 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
|
||||
};
|
||||
// Use a macro rather than mess with subtle mismatches
|
||||
// between member and non-member function pointers.
|
||||
#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
1049
depends/pack200/src/coding.cpp
Normal file
1049
depends/pack200/src/coding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
270
depends/pack200/src/coding.h
Normal file
270
depends/pack200/src/coding.h
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct unpacker;
|
||||
|
||||
#define INT_MAX_VALUE ((int)0x7FFFFFFF)
|
||||
#define INT_MIN_VALUE ((int)0x80000000)
|
||||
|
||||
#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
|
||||
#define CODING_B(x) ((x) >> 20 & 0xF)
|
||||
#define CODING_H(x) ((x) >> 8 & 0xFFF)
|
||||
#define CODING_S(x) ((x) >> 4 & 0xF)
|
||||
#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 \
|
||||
}
|
||||
|
||||
// For debugging purposes, some compilers do not like this and will complain.
|
||||
// #define long do_not_use_C_long_types_use_jlong_or_int
|
||||
// Use of the type "long" is problematic, do not use it.
|
||||
|
||||
struct coding
|
||||
{
|
||||
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;
|
||||
|
||||
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 uint parse(byte *&rp, int B, int H);
|
||||
static uint parse_lgH(byte *&rp, int B, int H, int lgH);
|
||||
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
|
||||
|
||||
uint 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void free(); // free self if isMalloc
|
||||
|
||||
// error handling
|
||||
static void abort(const char *msg = nullptr)
|
||||
{
|
||||
unpack_abort(msg);
|
||||
}
|
||||
};
|
||||
|
||||
enum coding_method_kind
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
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)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
B_MAX = 5,
|
||||
C_SLOP = B_MAX * 10
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Used only for asserts.
|
||||
bool 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();
|
||||
|
||||
// error handling
|
||||
// inline void abort(const char* msg);
|
||||
// inline void aborting();
|
||||
};
|
||||
|
||||
struct coding_method
|
||||
{
|
||||
value_stream vs0; // initial state snapshot (vs.meta==this)
|
||||
|
||||
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
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// 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);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
||||
|
||||
// inline void value_stream::abort(const char* msg) { cm->abort(msg); }
|
||||
// inline void value_stream::aborting() { cm->aborting(); }
|
442
depends/pack200/src/constants.h
Normal file
442
depends/pack200/src/constants.h
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
Java Class Version numbers history
|
||||
1.0 to 1.3.X 45,3
|
||||
1.4 to 1.4.X 46,0
|
||||
1.5 to 1.5.X 49,0
|
||||
1.6 to 1.5.x 50,0 NOTE Assumed for now
|
||||
*/
|
||||
|
||||
// classfile constants
|
||||
#define JAVA_MAGIC 0xCAFEBABE
|
||||
#define JAVA_MIN_MAJOR_VERSION 45
|
||||
#define JAVA_MIN_MINOR_VERSION 3
|
||||
#define JAVA5_MAX_MAJOR_VERSION 49
|
||||
#define JAVA5_MAX_MINOR_VERSION 0
|
||||
// NOTE: Assume for now
|
||||
#define JAVA6_MAX_MAJOR_VERSION 50
|
||||
#define JAVA6_MAX_MINOR_VERSION 0
|
||||
|
||||
// package file constants
|
||||
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
|
||||
#define JAVA5_PACKAGE_MAJOR_VERSION 150
|
||||
#define JAVA5_PACKAGE_MINOR_VERSION 7
|
||||
|
||||
#define JAVA6_PACKAGE_MAJOR_VERSION 160
|
||||
#define JAVA6_PACKAGE_MINOR_VERSION 1
|
||||
|
||||
// magic number for gzip streams (for processing pack200-gzip data)
|
||||
#define GZIP_MAGIC 0x1F8B0800
|
||||
#define GZIP_MAGIC_MASK 0xFFFFFF00 // last byte is variable "flg" field
|
||||
|
||||
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,
|
||||
|
||||
#define O_ATTR_DO(F) \
|
||||
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)*/
|
||||
#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)*/
|
||||
#define FIELD_ATTR_DO(F) \
|
||||
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)*/
|
||||
#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)*/
|
||||
#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)*/
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
#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)*/
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
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
|
||||
};
|
136
depends/pack200/src/defines.h
Normal file
136
depends/pack200/src/defines.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// random definitions
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef FULL
|
||||
#define FULL 1 /* Adds <500 bytes to the zipped final product. */
|
||||
#endif
|
||||
|
||||
#if FULL // define this if you want debugging and/or compile-time attributes
|
||||
#define IF_FULL(x) x
|
||||
#else
|
||||
#define IF_FULL(x) /*x*/
|
||||
#endif
|
||||
|
||||
// Error messages that we have
|
||||
#define ERROR_ENOMEM "Native allocation failed"
|
||||
#define ERROR_FORMAT "Corrupted pack file"
|
||||
#define ERROR_RESOURCE "Cannot extract resource file"
|
||||
#define ERROR_OVERFLOW "Internal buffer overflow"
|
||||
#define ERROR_INTERNAL "Internal error"
|
||||
|
||||
#define LOGFILE_STDOUT "-"
|
||||
#define LOGFILE_STDERR ""
|
||||
|
||||
#define lengthof(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
|
||||
#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
// bytes and byte arrays
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef LONGLONG jlong;
|
||||
typedef DWORDLONG julong;
|
||||
#define MKDIR(dir) mkdir(dir)
|
||||
#define getpid() _getpid()
|
||||
#define PATH_MAX MAX_PATH
|
||||
#define dup2(a, b) _dup2(a, b)
|
||||
#define strcasecmp(s1, s2) _stricmp(s1, s2)
|
||||
#define tempname _tempname
|
||||
#define sleep Sleep
|
||||
#else
|
||||
typedef signed char byte;
|
||||
#ifdef _LP64
|
||||
typedef long jlong;
|
||||
typedef long unsigned julong;
|
||||
#else
|
||||
typedef long long jlong;
|
||||
typedef long long unsigned julong;
|
||||
#endif
|
||||
#define MKDIR(dir) mkdir(dir, 0777);
|
||||
#endif
|
||||
|
||||
/* Must cast to void *, then size_t, then int. */
|
||||
#define ptrlowbits(x) ((int)(size_t)(void *)(x))
|
||||
|
||||
/* Back and forth from jlong to pointer */
|
||||
#define ptr2jlong(x) ((jlong)(size_t)(void *)(x))
|
||||
#define jlong2ptr(x) ((void *)(size_t)(x))
|
||||
|
||||
// Keys used by Java:
|
||||
#define UNPACK_DEFLATE_HINT "unpack.deflate.hint"
|
||||
|
||||
#define COM_PREFIX "com.sun.java.util.jar.pack."
|
||||
#define UNPACK_MODIFICATION_TIME COM_PREFIX "unpack.modification.time"
|
||||
#define DEBUG_VERBOSE COM_PREFIX "verbose"
|
||||
|
||||
#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200"
|
||||
|
||||
// The following are not known to the Java classes:
|
||||
#define UNPACK_REMOVE_PACKFILE COM_PREFIX "unpack.remove.packfile"
|
||||
|
||||
// Called from unpacker layers
|
||||
#define _CHECK_DO(t, x) \
|
||||
{ \
|
||||
if (t) \
|
||||
{ \
|
||||
x; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECK _CHECK_DO(aborting(), return)
|
||||
#define CHECK_(y) _CHECK_DO(aborting(), return y)
|
||||
#define CHECK_0 _CHECK_DO(aborting(), return 0)
|
||||
|
||||
#define CHECK_NULL(p) _CHECK_DO((p) == nullptr, return)
|
||||
#define CHECK_NULL_(y, p) _CHECK_DO((p) == nullptr, return y)
|
||||
#define CHECK_NULL_0(p) _CHECK_DO((p) == nullptr, return 0)
|
||||
|
||||
#define CHECK_COUNT(t) \
|
||||
if (t < 0) \
|
||||
{ \
|
||||
abort("bad value count"); \
|
||||
} \
|
||||
CHECK
|
||||
|
||||
#define STR_TRUE "true"
|
||||
#define STR_FALSE "false"
|
||||
|
||||
#define STR_TF(x) ((x) ? STR_TRUE : STR_FALSE)
|
||||
#define BOOL_TF(x) (((x) != nullptr &&strcmp((x), STR_TRUE) == 0) ? true : false)
|
||||
|
||||
#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT
|
489
depends/pack200/src/main.cpp
Normal file
489
depends/pack200/src/main.cpp
Normal file
@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return unpacker::run(argc, argv);
|
||||
}
|
||||
|
||||
unpacker *unpacker::non_mt_current = nullptr;
|
||||
unpacker *unpacker::current()
|
||||
{
|
||||
return non_mt_current;
|
||||
}
|
||||
static void set_current_unpacker(unpacker *u)
|
||||
{
|
||||
unpacker::non_mt_current = u;
|
||||
}
|
||||
|
||||
// Callback for fetching data, Unix style.
|
||||
static jlong read_input_via_stdio(unpacker *u, void *buf, jlong minlen, jlong maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
jlong 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;
|
||||
if (u->infileptr != nullptr)
|
||||
{
|
||||
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef WIN32
|
||||
// we prefer unbuffered inputs
|
||||
nr = (int)read(u->infileno, bufptr, readlen);
|
||||
#else
|
||||
nr = (int)fread(bufptr, 1, readlen, stdin);
|
||||
#endif
|
||||
}
|
||||
if (nr <= 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
nr = 0;
|
||||
}
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
}
|
||||
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d\n",
|
||||
// (int)minlen, (int)maxlen, (int)numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
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
|
||||
jlong 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;
|
||||
}
|
||||
|
||||
static void setup_gzin(unpacker *u)
|
||||
{
|
||||
gunzip *gzin = NEW(gunzip, 1);
|
||||
gzin->init(u);
|
||||
}
|
||||
|
||||
static const char *nbasename(const char *progname)
|
||||
{
|
||||
const char *slash = strrchr(progname, '/');
|
||||
if (slash != nullptr)
|
||||
progname = ++slash;
|
||||
return progname;
|
||||
}
|
||||
|
||||
static const char *usage_lines[] = {
|
||||
"Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", "\n", "Unpacking Options\n",
|
||||
" -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep "
|
||||
"(default)\n",
|
||||
" -r, --remove-pack-file remove input file after unpacking\n",
|
||||
" -v, --verbose increase program verbosity\n",
|
||||
" -q, --quiet set verbosity to lowest level\n",
|
||||
" -l{F}, --log-file={F} output to the given log file, or '-' for standard output "
|
||||
"(default)\n",
|
||||
" -?, -h, --help print this message\n",
|
||||
" -J{X} Java VM argument (ignored)\n", nullptr};
|
||||
|
||||
static void usage(unpacker *u, const char *progname, bool full = false)
|
||||
{
|
||||
// WinMain does not set argv[0] to the progrname
|
||||
progname = (progname != nullptr) ? nbasename(progname) : "unpack200";
|
||||
for (int i = 0; usage_lines[i] != nullptr; i++)
|
||||
{
|
||||
fprintf(stderr, usage_lines[i], progname);
|
||||
if (!full)
|
||||
{
|
||||
fprintf(stderr, "(For more information, run %s --help .)\n", progname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// argument parsing
|
||||
static char **init_args(int argc, char **argv, int &envargc)
|
||||
{
|
||||
const char *env = getenv("UNPACK200_FLAGS");
|
||||
ptrlist envargs;
|
||||
envargs.init();
|
||||
if (env != nullptr)
|
||||
{
|
||||
char *buf = (char *)strdup(env);
|
||||
const char *delim = "\n\t ";
|
||||
for (char *p = strtok(buf, delim); p != nullptr; p = strtok(nullptr, delim))
|
||||
{
|
||||
envargs.add(p);
|
||||
}
|
||||
}
|
||||
// allocate extra margin at both head and tail
|
||||
char **argp = NEW(char *, envargs.length() + argc + 1);
|
||||
char **argp0 = argp;
|
||||
int i;
|
||||
for (i = 0; i < envargs.length(); i++)
|
||||
{
|
||||
*argp++ = (char *)envargs.get(i);
|
||||
}
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
// note: skip argv[0] (program name)
|
||||
*argp++ = (char *)strdup(argv[i]); // make a scratch copy
|
||||
}
|
||||
*argp = nullptr; // sentinel
|
||||
envargc = envargs.length(); // report this count to next_arg
|
||||
envargs.free();
|
||||
return argp0;
|
||||
}
|
||||
|
||||
static int strpcmp(const char *str, const char *pfx)
|
||||
{
|
||||
return strncmp(str, pfx, strlen(pfx));
|
||||
}
|
||||
|
||||
static const char flag_opts[] = "vqrVh?";
|
||||
static const char string_opts[] = "HlJ";
|
||||
|
||||
static int next_arg(char **&argp)
|
||||
{
|
||||
char *arg = *argp;
|
||||
if (arg == nullptr || arg[0] != '-')
|
||||
{ // end of option list
|
||||
return 0;
|
||||
}
|
||||
// printf("opt: %s\n", arg);
|
||||
char ach = arg[1];
|
||||
if (ach == '\0')
|
||||
{
|
||||
// ++argp; // do not pop this arg
|
||||
return 0; // bare "-" is stdin/stdout
|
||||
}
|
||||
else if (arg[1] == '-')
|
||||
{ // --foo option
|
||||
static const char *keys[] = {"Hdeflate-hint=", "vverbose", "qquiet",
|
||||
"rremove-pack-file", "llog-file=", "Vversion",
|
||||
"hhelp", nullptr};
|
||||
if (arg[2] == '\0')
|
||||
{ // end of option list
|
||||
++argp; // pop the "--"
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; keys[i] != nullptr; i++)
|
||||
{
|
||||
const char *key = keys[i];
|
||||
char kch = *key++;
|
||||
if (strchr(key, '=') == nullptr)
|
||||
{
|
||||
if (!strcmp(arg + 2, key))
|
||||
{
|
||||
++argp; // pop option arg
|
||||
return kch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strpcmp(arg + 2, key))
|
||||
{
|
||||
*argp += 2 + strlen(key); // remove "--"+key from arg
|
||||
return kch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strchr(flag_opts, ach) != nullptr)
|
||||
{ // plain option
|
||||
if (arg[2] == '\0')
|
||||
{
|
||||
++argp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// in-place edit of "-vxyz" to "-xyz"
|
||||
arg += 1; // skip original '-'
|
||||
arg[0] = '-';
|
||||
*argp = arg;
|
||||
}
|
||||
// printf(" key => %c\n", ach);
|
||||
return ach;
|
||||
}
|
||||
else if (strchr(string_opts, ach) != nullptr)
|
||||
{ // argument-bearing option
|
||||
if (arg[2] == '\0')
|
||||
{
|
||||
if (argp[1] == nullptr)
|
||||
return -1; // no next arg
|
||||
++argp; // leave the argument in place
|
||||
}
|
||||
else
|
||||
{
|
||||
// in-place edit of "-Hxyz" to "xyz"
|
||||
arg += 2; // skip original '-H'
|
||||
*argp = arg;
|
||||
}
|
||||
// printf(" key => %c\n", ach);
|
||||
return ach;
|
||||
}
|
||||
return -1; // bad argument
|
||||
}
|
||||
|
||||
static const char sccsver[] = "1.30, 07/05/05";
|
||||
|
||||
// Usage: unpackage input.pack output.jar
|
||||
int unpacker::run(int argc, char **argv)
|
||||
{
|
||||
unpacker u;
|
||||
u.init(read_input_via_stdio);
|
||||
set_current_unpacker(&u);
|
||||
|
||||
jar jarout;
|
||||
jarout.init(&u);
|
||||
|
||||
int envargc = 0;
|
||||
char **argbuf = init_args(argc, argv, envargc);
|
||||
char **arg0 = argbuf + envargc;
|
||||
char **argp = argbuf;
|
||||
|
||||
int verbose = 0;
|
||||
char *logfile = nullptr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char *arg = (*argp == nullptr) ? "" : u.saveStr(*argp);
|
||||
bool isenvarg = (argp < arg0);
|
||||
int ach = next_arg(argp);
|
||||
bool hasoptarg = (ach != 0 && strchr(string_opts, ach) != nullptr);
|
||||
if (ach == 0 && argp >= arg0)
|
||||
break;
|
||||
if (isenvarg && argp == arg0 && hasoptarg)
|
||||
ach = 0; // don't pull from cmdline
|
||||
switch (ach)
|
||||
{
|
||||
case 'H':
|
||||
u.set_option(UNPACK_DEFLATE_HINT, *argp++);
|
||||
break;
|
||||
case 'v':
|
||||
++verbose;
|
||||
break;
|
||||
case 'q':
|
||||
verbose = 0;
|
||||
break;
|
||||
case 'r':
|
||||
u.set_option(UNPACK_REMOVE_PACKFILE, "1");
|
||||
break;
|
||||
case 'l':
|
||||
logfile = *argp++;
|
||||
break;
|
||||
case 'J':
|
||||
argp += 1;
|
||||
break; // skip ignored -Jxxx parameter
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
usage(&u, argv[0], true);
|
||||
exit(1);
|
||||
|
||||
default:
|
||||
const char *inenv = isenvarg ? " in ${UNPACK200_FLAGS}" : "";
|
||||
if (hasoptarg)
|
||||
fprintf(stderr, "Missing option string%s: %s\n", inenv, arg);
|
||||
else
|
||||
fprintf(stderr, "Unrecognized argument%s: %s\n", inenv, arg);
|
||||
usage(&u, argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
u.set_option(DEBUG_VERBOSE, u.saveIntStr(verbose));
|
||||
}
|
||||
|
||||
const char *source_file = *argp++;
|
||||
const char *destination_file = *argp++;
|
||||
|
||||
if (source_file == nullptr || destination_file == nullptr || *argp != nullptr)
|
||||
{
|
||||
usage(&u, argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
fprintf(stderr, "Unpacking from %s to %s\n", source_file, destination_file);
|
||||
}
|
||||
bool &remove_source = u.remove_packfile;
|
||||
|
||||
if (strcmp(source_file, "-") == 0)
|
||||
{
|
||||
remove_source = false;
|
||||
u.infileno = fileno(stdin);
|
||||
}
|
||||
else
|
||||
{
|
||||
u.infileptr = fopen(source_file, "rb");
|
||||
if (u.infileptr == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open input file: %s\n", source_file);
|
||||
exit(3); // Called only from the native standalone unpacker
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(destination_file, "-") == 0)
|
||||
{
|
||||
jarout.jarfp = stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
jarout.openJarFile(destination_file);
|
||||
assert(jarout.jarfp != nullptr);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
u.dump_options();
|
||||
|
||||
char peek[4];
|
||||
int magic;
|
||||
|
||||
// check for GZIP input
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
|
||||
{
|
||||
// Oops; must slap an input filter on this data.
|
||||
setup_gzin(&u);
|
||||
u.gzin->start(magic);
|
||||
if (!u.aborting())
|
||||
{
|
||||
u.start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 (;;)
|
||||
{
|
||||
if (u.aborting())
|
||||
break;
|
||||
|
||||
// Each trip through this loop unpacks one segment
|
||||
// and then resets the unpacker.
|
||||
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
|
||||
{
|
||||
if (u.aborting())
|
||||
break;
|
||||
u.write_file_to_jar(filep);
|
||||
}
|
||||
if (u.aborting())
|
||||
break;
|
||||
|
||||
// Peek ahead for more data.
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if (magic != (int)JAVA_PACKAGE_MAGIC)
|
||||
{
|
||||
if (magic != EOF_MAGIC)
|
||||
u.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));
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
if (u.aborting())
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", u.get_abort_message());
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (u.infileptr != nullptr)
|
||||
{
|
||||
fclose(u.infileptr);
|
||||
u.infileptr = nullptr;
|
||||
}
|
||||
|
||||
if (!u.aborting() && remove_source)
|
||||
remove(source_file);
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
fprintf(stderr, "unpacker completed with status=%d\n", status);
|
||||
}
|
||||
|
||||
u.finish();
|
||||
|
||||
u.free(); // tidy up malloc blocks
|
||||
set_current_unpacker(nullptr); // clean up global pointer
|
||||
|
||||
return status;
|
||||
}
|
5105
depends/pack200/src/unpack.cpp
Normal file
5105
depends/pack200/src/unpack.cpp
Normal file
File diff suppressed because it is too large
Load Diff
585
depends/pack200/src/unpack.h
Normal file
585
depends/pack200/src/unpack.h
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Global Structures
|
||||
struct jar;
|
||||
struct gunzip;
|
||||
struct band;
|
||||
struct cpool;
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct inner_class;
|
||||
struct value_stream;
|
||||
|
||||
struct cpindex
|
||||
{
|
||||
uint 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(uint 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_;
|
||||
}
|
||||
};
|
||||
|
||||
struct cpool
|
||||
{
|
||||
uint nentries;
|
||||
entry *entries;
|
||||
entry *first_extra_entry;
|
||||
uint 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];
|
||||
|
||||
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);
|
||||
|
||||
int outputIndexLimit; // index limit after renumbering
|
||||
ptrlist outputEntries; // list of entry* needing output idx assigned
|
||||
|
||||
entry **hashTab;
|
||||
uint hashTabLength;
|
||||
entry *&hashTabRef(byte tag, bytes &b);
|
||||
entry *ensureUtf8(bytes &b);
|
||||
entry *ensureClass(bytes &b);
|
||||
|
||||
// Well-known Utf8 symbols.
|
||||
enum
|
||||
{
|
||||
#define SNAME(n, s) s_##s,
|
||||
ALL_ATTR_DO(SNAME)
|
||||
#undef SNAME
|
||||
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]);
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
int getCount(byte tag)
|
||||
{
|
||||
assert((uint)tag < CONSTANT_Limit);
|
||||
return tag_count[tag];
|
||||
}
|
||||
cpindex *getIndex(byte tag)
|
||||
{
|
||||
assert((uint)tag < CONSTANT_Limit);
|
||||
return &tag_index[tag];
|
||||
}
|
||||
cpindex *getKQIndex(); // uses cur_descr
|
||||
|
||||
void expandSignatures();
|
||||
void initMemberIndexes();
|
||||
|
||||
void computeOutputOrder();
|
||||
void computeOutputIndexes();
|
||||
void resetOutputIndexes();
|
||||
|
||||
// error handling
|
||||
inline void abort(const char *msg);
|
||||
inline bool aborting();
|
||||
};
|
||||
|
||||
/*
|
||||
* The unpacker provides the entry points to the unpack engine,
|
||||
* as well as maintains the state of the engine.
|
||||
*/
|
||||
struct unpacker
|
||||
{
|
||||
// One element of the resulting JAR.
|
||||
struct file
|
||||
{
|
||||
const char *name;
|
||||
julong 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);
|
||||
}
|
||||
};
|
||||
|
||||
// global pointer to self, if not running under JNI (not multi-thread safe)
|
||||
static unpacker *non_mt_current;
|
||||
|
||||
// if running Unix-style, here are the inputs and outputs
|
||||
FILE *infileptr; // buffered
|
||||
int infileno; // unbuffered
|
||||
bytes inbytes; // direct
|
||||
gunzip *gzin; // gunzip filter, if any
|
||||
jar *jarout; // output JAR file
|
||||
|
||||
// pointer to self, for U_NEW macro
|
||||
unpacker *u;
|
||||
|
||||
// private abort message string, allocated to PATH_MAX*2
|
||||
const char *abort_message;
|
||||
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
|
||||
bool strip_compile;
|
||||
bool strip_debug;
|
||||
bool strip_jcov;
|
||||
bool remove_packfile;
|
||||
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?
|
||||
julong bytes_read;
|
||||
int unsized_bytes_read;
|
||||
|
||||
// callback to read at least one byte, up to available input
|
||||
typedef jlong (*read_input_fn_t)(unpacker *self, void *buf, jlong minlen, jlong 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
|
||||
|
||||
// engine state
|
||||
band *all_bands; // indexed by band_number
|
||||
byte *meta_rp; // read-pointer into (copy of) band_headers
|
||||
cpool 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 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
|
||||
julong 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)
|
||||
julong bytes_read_before_reset;
|
||||
julong bytes_written_before_reset;
|
||||
int files_written_before_reset;
|
||||
int classes_written_before_reset;
|
||||
int segments_read_before_reset;
|
||||
|
||||
// attribute state
|
||||
struct layout_definition
|
||||
{
|
||||
uint 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.
|
||||
uint flag_limit; // 32 or 63, depending on archive_options bit
|
||||
julong predef; // mask of built-in definitions
|
||||
julong 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();
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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, uint count); // recursive helper
|
||||
|
||||
layout_definition *getLayout(uint idx)
|
||||
{
|
||||
if (idx >= (uint)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;
|
||||
}
|
||||
|
||||
// Return flag_count if idx is predef and not redef, else zero.
|
||||
int predefCount(uint idx);
|
||||
|
||||
bool isRedefined(uint idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)((redef >> idx) & 1);
|
||||
}
|
||||
bool isPredefined(uint idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)(((predef & ~redef) >> idx) & 1);
|
||||
}
|
||||
julong flagIndexMask()
|
||||
{
|
||||
return (predef | redef);
|
||||
}
|
||||
bool isIndex(uint 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 < (uint)overflow_count.length());
|
||||
}
|
||||
int &getCount(uint idx)
|
||||
{
|
||||
assert(isIndex(idx));
|
||||
if (idx < flag_limit)
|
||||
return flag_count[idx];
|
||||
else
|
||||
return overflow_count.get(idx - flag_limit);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
||||
void abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Option management methods
|
||||
bool set_option(const char *option, const char *value);
|
||||
const char *get_option(const char *option);
|
||||
|
||||
void dump_options();
|
||||
|
||||
// Fetching input.
|
||||
bool ensure_input(jlong 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();
|
||||
|
||||
// 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);
|
||||
}
|
||||
const char *get_abort_message();
|
||||
void abort(const char *s = nullptr);
|
||||
bool aborting()
|
||||
{
|
||||
return abort_message != nullptr;
|
||||
}
|
||||
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
|
||||
|
||||
// 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(jlong 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;
|
||||
}
|
||||
uint to_bci(uint 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, jlong 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, julong 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);
|
||||
};
|
||||
|
||||
inline void cpool::abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
inline bool cpool::aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
91
depends/pack200/src/utils.cpp
Normal file
91
depends/pack200/src/utils.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "constants.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
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
|
||||
{
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void unpack_abort(const char *msg, unpacker *u)
|
||||
{
|
||||
if (msg == nullptr)
|
||||
msg = "corrupt pack file or internal error";
|
||||
if (u == nullptr)
|
||||
u = unpacker::current();
|
||||
if (u == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: unpacker: %s\n", msg);
|
||||
::abort();
|
||||
return;
|
||||
}
|
||||
u->abort(msg);
|
||||
}
|
||||
|
||||
bool unpack_aborting(unpacker *u)
|
||||
{
|
||||
if (u == nullptr)
|
||||
u = unpacker::current();
|
||||
if (u == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: unpacker: no current instance\n");
|
||||
::abort();
|
||||
return true;
|
||||
}
|
||||
return u->aborting();
|
||||
}
|
54
depends/pack200/src/utils.h
Normal file
54
depends/pack200/src/utils.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Definitions of our util functions
|
||||
|
||||
void *must_malloc(size_t size);
|
||||
|
||||
// overflow management
|
||||
#define OVERFLOW ((size_t) - 1)
|
||||
#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
|
||||
|
||||
inline size_t scale_size(size_t size, size_t 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;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2, int size3)
|
||||
{
|
||||
return add_size(add_size(size1, size2), size3);
|
||||
}
|
||||
|
||||
// These may be expensive, because they have to go via Java TSD,
|
||||
// if the optional u argument is missing.
|
||||
struct unpacker;
|
||||
extern void unpack_abort(const char *msg, unpacker *u = nullptr);
|
||||
extern bool unpack_aborting(unpacker *u = nullptr);
|
||||
|
610
depends/pack200/src/zip.cpp
Normal file
610
depends/pack200/src/zip.cpp
Normal file
@ -0,0 +1,610 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: Lifted from uncrunch.c from jdk sources
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#ifdef NO_ZLIB
|
||||
|
||||
inline bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#define Z_NULL NULL
|
||||
|
||||
#else // Have ZLIB
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
|
||||
{
|
||||
return crc32(c, ptr, len);
|
||||
}
|
||||
|
||||
#endif // End of ZLIB
|
||||
|
||||
#ifdef sparc
|
||||
#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
|
||||
#else
|
||||
#define SWAP_BYTES(a) (a)
|
||||
#endif
|
||||
|
||||
#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
|
||||
|
||||
#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
|
||||
|
||||
void jar::init(unpacker *u_)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint fname_length = (uint)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);
|
||||
|
||||
// required version
|
||||
header[3] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
central_directory_count++;
|
||||
}
|
||||
|
||||
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint crc)
|
||||
{
|
||||
uint fname_length = (uint)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);
|
||||
|
||||
// Version
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT;
|
||||
|
||||
void jar::write_central_directory()
|
||||
{
|
||||
bytes mc;
|
||||
mc.set(marker_comment);
|
||||
|
||||
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);
|
||||
|
||||
// Write the central directory.
|
||||
write_data(central_directory.b);
|
||||
|
||||
// Write the End of Central Directory structure.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Write the comment.
|
||||
write_data(mc);
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry and copy the file data
|
||||
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
int clen = 0;
|
||||
|
||||
uint crc = get_crc32(0, Z_NULL, 0);
|
||||
if (head.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)head.ptr, (uint)head.len);
|
||||
if (tail.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)tail.ptr, (uint)tail.len);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
|
||||
* time (date in high two bytes, time in low two bytes allowing magnitude
|
||||
* comparison).
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef _REENTRANT // solaris
|
||||
extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
|
||||
#else
|
||||
#define gmtime_r(t, s) gmtime(t)
|
||||
#endif
|
||||
/*
|
||||
* Return the Unix time in DOS format
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/* Returns true on success, and will set the clen to the compressed
|
||||
length, the caller should verify if true and clen less than the
|
||||
input data
|
||||
*/
|
||||
bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
|
||||
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
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Callback for fetching data from a GZIP input stream
|
||||
static jlong read_input_via_gzip(unpacker *u, void *buf, jlong minlen, jlong maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
jlong 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)
|
||||
{
|
||||
u->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)
|
||||
u->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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (aborting())
|
||||
return;
|
||||
|
||||
// now the input stream is ready to read into the inflater
|
||||
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
abort("cannot create input");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void gunzip::read_fixed_field(char *buf, size_t buflen)
|
||||
{
|
||||
if (aborting())
|
||||
return;
|
||||
jlong nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
|
||||
if ((size_t)nr != buflen)
|
||||
u->abort("short stream header");
|
||||
}
|
130
depends/pack200/src/zip.h
Normal file
130
depends/pack200/src/zip.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
struct unpacker;
|
||||
|
||||
struct jar
|
||||
{
|
||||
// JAR file writer
|
||||
FILE *jarfp;
|
||||
int default_modtime;
|
||||
|
||||
// Used by unix2dostime:
|
||||
int modtime_cache;
|
||||
uint32_t dostime_cache;
|
||||
|
||||
// Private members
|
||||
fillbytes central_directory;
|
||||
ushort central_directory_count;
|
||||
uint output_file_offset;
|
||||
fillbytes deflated; // temporary buffer
|
||||
|
||||
// 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);
|
||||
|
||||
void init(unpacker *u_);
|
||||
|
||||
void free()
|
||||
{
|
||||
central_directory.free();
|
||||
deflated.free();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// The definitions of these depend on the NO_ZLIB option:
|
||||
bool deflate_bytes(bytes &head, bytes &tail);
|
||||
static uint get_crc32(uint c, unsigned char *ptr, uint len);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
||||
|
||||
struct gunzip
|
||||
{
|
||||
// optional gzip input stream control block
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
void *read_input_fn; // underlying byte stream
|
||||
void *zstream; // inflater state
|
||||
char inbuf[1 << 14]; // input buffer
|
||||
|
||||
void init(unpacker *u_); // pushes new value on u->read_input_fn
|
||||
|
||||
void free();
|
||||
|
||||
void start(int magic);
|
||||
|
||||
// private stuff
|
||||
void read_fixed_field(char *buf, size_t buflen);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user