diff --git a/Document.txt b/Document.txt index 1fdad23..efa1e09 100755 --- a/Document.txt +++ b/Document.txt @@ -444,8 +444,16 @@ int main(int argc, char** argv) { set_verbosity(VERBOSITY_NOTHING); . . + /* Read PP HEADER */ + /* CONVERT PPHEADER to native format numbers */ + mdi=ppheader[BRMDI_INDEX]; + data_size=ppheader[LBLREC_INDEX]-ppheader[LBEXT_INDEX]; + pack=ppheader[LBPACK_INDEX] + expected_size=ppheader[LBROW_INDEX]*ppheader[LBNPT_INDEX]; + /* Read field data */ . - unpack_ppfield(&ppheader, ppdata, unpacked_data, &root); + . + unpack_ppfield(mdi, data_size, packed_data, pack, expected_size, unpacked_data, &root); . . . diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fc772cb --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +major=2 +minor=0 +rel=4 +CC=cc + +OPTS=-O3 -I./include -D_LARGEFILE_SOURCE -D_LARGEFILE_SOURCE64 -D_FILE_OFFSET_BITS=64 -fpic + +OBJS=convert_float_ibm_to_ieee32.o extract_wgdos_row.o rlencode.o wgdos_decode_row_parameters.o \ + convert_float_ieee32_to_ibm.o logerrors.o uascii.o wgdos_expand_row_to_data.o \ + extract_bitmaps.o pack_ppfield.o unpack_ppfield.o wgdos_pack.o extract_nbit_words.o \ + read_wgdos_bitmaps.ibm.o wgdos_decode_field_parameters.o wgdos_unpack.o + +libmo_unpack: $(OBJS) + mkdir -p lib + ar -cr lib/libmo_unpack.a $(OBJS) + ld -shared -soname libmo_unpack.so.$(major) $(OBJS) -o lib/libmo_unpack.so.$(major).$(minor).$(rel) + @echo $(shell cd lib; ln -s libmo_unpack.so.$(major).$(minor).$(rel) libmo_unpack.so.$(major).$(minor) && \ + ln -s libmo_unpack.so.$(major).$(minor) libmo_unpack.so.$(major) && \ + ln -s libmo_unpack.so.$(major) libmo_unpack.so ) + +%.o: %.c + $(CC) -c $(OPTS) $< -o $@ + +clean: + rm -f *.o lib/libmo_unpack.so* diff --git a/include/wgdosstuff.h b/include/wgdosstuff.h index 3862d25..f736ef3 100644 --- a/include/wgdosstuff.h +++ b/include/wgdosstuff.h @@ -44,6 +44,8 @@ #define MAX_MESSAGE_SIZE 1024 + #define INVALID_PACKING_ACCURACY 31 + #include "logerrors.h" #ifndef TRUE diff --git a/make_library b/make_library index 171ccd4..edd6cef 100755 --- a/make_library +++ b/make_library @@ -32,7 +32,7 @@ # Edit these values when building a new version of the library major=2 minor=0 -rel=3 +rel=4 os=`uname` if [ _$os = "_OS/390" ] diff --git a/pack_ppfield.c b/pack_ppfield.c index f96b65e..80b5e69 100644 --- a/pack_ppfield.c +++ b/pack_ppfield.c @@ -63,6 +63,7 @@ int pack_ppfield(float mdi, int ncols, int nrows, float* data, int pack, int bpa int count; int retcode=0; int unpacked_size=nrows*ncols; + int pack_rcode=0; /* return code from the wgdos_pack function */ function subroutine; set_function_name(__func__, &subroutine, parent); @@ -84,10 +85,15 @@ int pack_ppfield(float mdi, int ncols, int nrows, float* data, int pack, int bpa case WGDOS_PACKED: /* WGDOS packing packs as a bytestream, MSB first */ MO_syslog(VERBOSITY_INFO, "WGDOS packing data", &subroutine); - if (wgdos_pack(ncols, nrows, data, mdi, bpacc, packed, packed_size, parent)) { + pack_rcode = wgdos_pack(ncols, nrows, data, mdi, bpacc, packed, packed_size, parent); + if (pack_rcode != 0) { /* Couldn't pack, so remember this when exiting */ MO_syslog(VERBOSITY_INFO, "wgdos_pack Failed", &subroutine); - retcode=1; + if (pack_rcode == INVALID_PACKING_ACCURACY) { + retcode=INVALID_PACKING_ACCURACY; + } else { + retcode=1; + } } break; case RLE_PACKED: diff --git a/wgdos_pack.c b/wgdos_pack.c index ee93476..fccb630 100644 --- a/wgdos_pack.c +++ b/wgdos_pack.c @@ -39,6 +39,14 @@ * SRCE checkin. Type: Undef * Reason: Reordering code, fixing bugs and testing compatability with genuine data and adding comments * + * Revision 2.2 2014/11/27 hshep + * SRCE checkin. Type: Update + * Reason: Bug fix in the initial bitshifting used to pack a row of data + * + * Revision 2.2.1 2014/12/08 hshep + * SRCE checkin. Type: Update + * Reason: Add return code 31, and bug fix for integer overflow when calculating + * spread * Information: */ @@ -48,6 +56,7 @@ #include #include #include +#include /* Package header files used */ #include "wgdosstuff.h" #include "logerrors.h" @@ -142,6 +151,9 @@ int wgdos_pack( int zeros_count; /* Number of bitmapped zeros */ int ndata; /* Number of non-bitmapped data items */ unsigned int spread; /* Spread of values in each row */ + float f_spread; /* A floating point value of spread */ + float epsilon_spread; /* Accuracy for floating point comparison of + spread */ int bpp; /* Number of bits required to store the packed values */ int bitmap_size; @@ -168,6 +180,7 @@ int wgdos_pack( return 1; } + epsilon_spread = 0.00001; wgdos_field_header_pointer=(void*)packed_data; bitmap_size=(ncols+7)/8; size_of_packed_field=0; @@ -231,11 +244,22 @@ int wgdos_pack( /* Calculate the number of bits required to contain the interval at the required accuracy */ spread=(maxval-minval)/accuracy; spread+=((maxval-minval)>=accuracy); - for (bpp=0;spread;spread=spread>>1,bpp++) {/*nothing*/} + /* It is possible to get an error where the value of spread becomes far + too large for the capacity of an unsigned integer. Therefore + we check that spread is smaller than the max value for an unsigned + integer ie. 4294967295 */ + f_spread = (maxval-minval)/accuracy; + f_spread += (float) ((maxval-minval)>=accuracy); + if (f_spread <= (float)UINT_MAX-epsilon_spread) { + for (bpp=0;spread;spread=spread>>1,bpp++) {/*nothing*/} + } else { + //override to failure + bpp = 32; + } if (bpp>31) { snprintf(message, MAX_MESSAGE_SIZE, "Data spread over the row (%f - %f)too large to manage at this accuracy (%f)", minval, maxval, accuracy); MO_syslog(VERBOSITY_ERROR, message, &subroutine); - return 1; + return INVALID_PACKING_ACCURACY; } snprintf(message, MAX_MESSAGE_SIZE, "scale %d min %f max %f accuracy %f bpacc %d ndata %d bpp %d", spread, minval, maxval, accuracy, bpacc,ndata, bpp); @@ -380,7 +404,7 @@ int bitstuff(unsigned char* byte, int bitnum, unsigned int value, unsigned int n } bitshift=8-(bitnum+nbits)%8; /* How many bits to shift value so it occupies the right byte positions */ - shifted=value<