diff options
Diffstat (limited to 'libgcobol/intrinsic.cc')
-rw-r--r-- | libgcobol/intrinsic.cc | 1546 |
1 files changed, 898 insertions, 648 deletions
diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc index 345d3ac..c85b263 100644 --- a/libgcobol/intrinsic.cc +++ b/libgcobol/intrinsic.cc @@ -28,21 +28,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Operational note for COBOL intrinsic functions: - - In general, the parameters to these functions are cblc_field_t pointers - along with an offset, size, and for some functions the "allflags", which - indicate that the variable is a table that was referenced as TABL(ALL) +/* COBOL intrinsic functions. + * + * In general, the parameters to these functions are cblc_field_t pointers + * along with an offset, size, and for some functions the "allflags", which + * indicate that the variable is a table that was referenced as TABL(ALL) + */ +#include <langinfo.h> - */ +#include <cctype> +#include <cmath> +#include <cstring> +#include <ctime> -#include <time.h> -#include <math.h> #include <algorithm> -#include <cctype> -#include <langinfo.h> -#include <string.h> +#include <vector> + +#include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -51,11 +55,12 @@ #include "libgcobol.h" #include "charmaps.h" + #pragma GCC diagnostic ignored "-Wformat-truncation" #define JD_OF_1601_01_02 2305812.5 -#define WEIRD_TRANSCENDENT_RETURN_VALUE (0.0Q) +#define WEIRD_TRANSCENDENT_RETURN_VALUE GCOB_FP128_LITERAL (0.0) #define NO_RDIGITS (0) struct cobol_tm @@ -81,11 +86,11 @@ static int is_leap_year(int); typedef char * PCHAR; static void -trim_trailing_spaces(PCHAR left, PCHAR &right) +trim_trailing_spaces(PCHAR left, PCHAR &right, int mapped_space) { while( right > left ) { - if( *(right-1) != internal_space ) + if( *(right-1) != mapped_space ) { break; } @@ -94,12 +99,13 @@ trim_trailing_spaces(PCHAR left, PCHAR &right) } static bool -is_zulu_format(PCHAR left, PCHAR &right) +is_zulu_format(PCHAR left, PCHAR &right, charmap_t *charmap) { + int char_Z = charmap->mapped_character(ascii_Z); bool retval = false; if( right > left ) { - retval = std::toupper((unsigned char)*(right-1)) == internal_Z; + retval = std::toupper((unsigned char)*(right-1)) == char_Z; } return retval; } @@ -162,7 +168,7 @@ JD_to_DOW(double JD) static char * -timespec_to_string(char *retval, struct timespec &tp) +timespec_to_string(char *retval, struct cbl_timespec &tp) { /* Returns a 21-character string: @@ -226,7 +232,8 @@ string_to_dest(cblc_field_t *dest, const char *psz) size_t dest_length = dest->capacity; size_t source_length = strlen(psz); size_t length = std::min(dest_length, source_length); - memset(dest->data, internal_space, dest_length); + charmap_t *charmap = __gg__get_charmap(dest->encoding); + memset(dest->data, charmap->mapped_character(ascii_space), dest_length); memcpy(dest->data, psz, length); } @@ -243,9 +250,12 @@ struct input_state nsubscript = N; if(N) { - subscript_alls = (bool *) malloc(nsubscript); - subscripts = (size_t *)malloc(nsubscript); - subscript_limits = (size_t *)malloc(nsubscript); + subscript_alls = static_cast<bool *>(malloc(nsubscript)); + subscripts = static_cast<size_t *>(malloc(nsubscript)); + subscript_limits = static_cast<size_t *>(malloc(nsubscript)); + massert(subscript_alls); + massert(subscripts); + massert(subscript_limits); } done = false; } @@ -373,7 +383,7 @@ year_to_yyyy(int arg1, int arg2, int arg3) static double -get_value_as_double_from_qualified_field( cblc_field_t *input, +get_value_as_double_from_qualified_field( const cblc_field_t *input, size_t input_o, size_t input_s) { @@ -404,11 +414,11 @@ get_value_as_double_from_qualified_field( cblc_field_t *input, } static -_Float128 kahan_summation(size_t ncount, +GCOB_FP128 kahan_summation(size_t ncount, cblc_field_t **source, - size_t *source_o, - size_t *source_s, - int *flags, + const size_t *source_o, + const size_t *source_s, + const int *flags, size_t *k_count) { // We use compensated addition. Look up Kahan summation. @@ -418,11 +428,11 @@ _Float128 kahan_summation(size_t ncount, // an aggressive optimizing compiler from just making it go away. *k_count = 0; - _Float128 sum = 0; - volatile _Float128 kahan_c = 0; - _Float128 input; - _Float128 y; - _Float128 t; + GCOB_FP128 sum = 0; + volatile GCOB_FP128 kahan_c = 0; + GCOB_FP128 input; + GCOB_FP128 y; + GCOB_FP128 t; for(size_t i=0; i<ncount; i++) { @@ -450,24 +460,24 @@ _Float128 kahan_summation(size_t ncount, } static -_Float128 +GCOB_FP128 variance( size_t ncount, cblc_field_t **source, - size_t *source_o, - size_t *source_s, - int *flags) + const size_t *source_o, + const size_t *source_s, + const int *flags) { // In order to avoid catastrophic cancellation, we are going to use an // algorithm that is a bit wasteful of time, but is described as particularly // robust. - _Float128 retval = 0; + GCOB_FP128 retval = 0; if( ncount ) { // First, we calculate the mean of the input variables, which we will use // as an offset in the second stage: size_t k_count; - _Float128 offset = kahan_summation( ncount, + GCOB_FP128 offset = kahan_summation( ncount, source, source_o, source_s, @@ -478,11 +488,11 @@ variance( size_t ncount, // Next, we use Welford's algorithm on the residuals: size_t count = 0; - _Float128 mean = 0; - _Float128 M2 = 0; - _Float128 delta; - _Float128 delta2; - _Float128 newValue; + GCOB_FP128 mean = 0; + GCOB_FP128 M2 = 0; + GCOB_FP128 delta; + GCOB_FP128 delta2; + GCOB_FP128 newValue; for(size_t i=0; i<ncount; i++) { @@ -516,7 +526,8 @@ variance( size_t ncount, static void -get_all_time( char *stime, +get_all_time( const cblc_field_t *dest, // needed for the target encoding + char *stime, const struct cobol_tm &ctm) { // This routine represents a universal source for all output formatted date @@ -542,14 +553,14 @@ get_all_time( char *stime, // days of January show up in the final week of the prior year. sprintf(stime, - "%4.4u%2.2u%2.2uT" // YYYYMMSS - "%2.2u%2.2u%2.2u" // hhmmss - ".%9.9u" // .sssssssss - "%c%2.2u%2.2u" // +hhmm - "W%2.2u" // Www - "%1u" // DOW [1-7], 1 for Monday - "%3.3u" // DDD day of year, 001 - 365,366 - "%4.4u", // ZZZZ Year for YYYY-Www-D + "%4.4d%2.2d%2.2dT" // YYYYMMSS + "%2.2d%2.2d%2.2d" // hhmmss + ".%9.9d" // .sssssssss + "%c%2.2d%2.2d" // +hhmm + "W%2.2d" // Www + "%1d" // DOW [1-7], 1 for Monday + "%3.3d" // DDD day of year, 001 - 365,366 + "%4.4d", // ZZZZ Year for YYYY-Www-D ctm.YYYY, ctm.MM, ctm.DD, @@ -564,8 +575,9 @@ get_all_time( char *stime, ctm.day_of_week+1, ctm.day_of_year, ctm.ZZZZ); - // We might be operating in EBCDIC: - ascii_to_internal_str(stime, strlen(stime)); + __gg__convert_encoding(PTRCAST(char, stime), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); } static @@ -682,7 +694,7 @@ populate_ctm_from_JD(struct cobol_tm &ctm, double JD ) static void populate_ctm_from_date( struct cobol_tm &ctm, - cblc_field_t *pdate, + const cblc_field_t *pdate, size_t pdate_offset, size_t pdate_size) { @@ -716,10 +728,10 @@ populate_ctm_from_double_time(struct cobol_tm &ctm, double time) static void populate_ctm_from_time( struct cobol_tm &ctm, - cblc_field_t *ptime, + const cblc_field_t *ptime, size_t ptime_o, size_t ptime_s, - cblc_field_t *poffset, + const cblc_field_t *poffset, size_t poffset_o, size_t poffset_s) { @@ -786,8 +798,11 @@ convert_to_zulu(cobol_tm &ctm) static void -ftime_replace(char *dest, char const * const dest_end, - char const *source, char const * const source_end, +ftime_replace(char *dest, + char const * const dest_end, + char const * source, + char const * const source_end, + charmap_t * charmap_source, char const * const ftime) { // This routine is highly dependent on the source format being correct. @@ -796,24 +811,34 @@ ftime_replace(char *dest, char const * const dest_end, bool saw_decimal_point = false; bool saw_plus_sign = false; char decimal_point = __gg__get_decimal_point(); - static const int OFFSET_TO_YYYY = 0; - static const int OFFSET_TO_MM = 4; - static const int OFFSET_TO_DD = 6; - static const int OFFSET_TO_HOUR = 9; - static const int OFFSET_TO_MINUTE = 11; - static const int OFFSET_TO_SECOND = 13; - static const int OFFSET_TO_FRACTION = 16; - static const int OFFSET_TO_OFFSET = 25; - static const int OFFSET_TO_OFFSET_HOUR = 26; - static const int OFFSET_TO_OFFSET_MINUTE = 28; - static const int OFFSET_TO_WEEK = 30; - static const int OFFSET_TO_DOW = 33; - static const int OFFSET_TO_DOY = 34; - static const int OFFSET_TO_ZZZZ = 37; + static const int OFFSET_TO_YYYY = 0; + static const int OFFSET_TO_MM = 4; + static const int OFFSET_TO_DD = 6; + static const int OFFSET_TO_HOUR = 9; + static const int OFFSET_TO_MINUTE = 11; + static const int OFFSET_TO_SECOND = 13; + static const int OFFSET_TO_FRACTION = 16; + static const int OFFSET_TO_OFFSET = 25; + static const int OFFSET_TO_OFFSET_HOUR = 26; + static const int OFFSET_TO_OFFSET_MINUTE = 28; + static const int OFFSET_TO_WEEK = 30; + static const int OFFSET_TO_DOW = 33; + static const int OFFSET_TO_DOY = 34; + static const int OFFSET_TO_ZZZZ = 37; + + int source_Y = charmap_source->mapped_character(ascii_Y ); + int source_W = charmap_source->mapped_character(ascii_W ); + int source_s = charmap_source->mapped_character(ascii_s ); + int source_m = charmap_source->mapped_character(ascii_m ); + int source_h = charmap_source->mapped_character(ascii_h ); + int source_plus = charmap_source->mapped_character(ascii_plus); + int source_D = charmap_source->mapped_character(ascii_D ); + int source_M = charmap_source->mapped_character(ascii_M ); + while( source < source_end && dest < dest_end ) { char fchar = *source; - if( fchar == internal_Y ) + if( fchar == source_Y ) { // This can only be a YYYY // But, we have a choice. If there is a 'W' in the format, then we @@ -822,7 +847,7 @@ ftime_replace(char *dest, char const * const dest_end, const char *p = source; while(p < source_end) { - if( *p++ == internal_W ) + if( *p++ == source_W ) { src = ftime + OFFSET_TO_ZZZZ; } @@ -830,21 +855,21 @@ ftime_replace(char *dest, char const * const dest_end, ncount = 4; } - else if( fchar == internal_M ) + else if( fchar == source_M ) { // This can only be a MM ncount = 2; src = ftime + OFFSET_TO_MM; } - else if( fchar == internal_D ) + else if( fchar == source_D ) { // It can be a D, DD or DDD - if( source[2] == internal_D ) + if( source[2] == source_D ) { ncount = 3; src = ftime + OFFSET_TO_DOY; } - else if( source[1] == internal_D ) + else if( source[1] == source_D ) { ncount = 2; src = ftime + OFFSET_TO_DD; @@ -855,13 +880,13 @@ ftime_replace(char *dest, char const * const dest_end, src = ftime + OFFSET_TO_DOW; } } - else if( fchar == internal_plus ) + else if( fchar == source_plus ) { saw_plus_sign = true; ncount = 1; src = ftime + OFFSET_TO_OFFSET; } - else if( fchar == internal_h ) + else if( fchar == source_h ) { ncount = 2; if(saw_plus_sign) @@ -873,7 +898,7 @@ ftime_replace(char *dest, char const * const dest_end, src = ftime + OFFSET_TO_HOUR; } } - else if( fchar == internal_m ) + else if( fchar == source_m ) { ncount = 2; if(saw_plus_sign) @@ -891,7 +916,7 @@ ftime_replace(char *dest, char const * const dest_end, ncount = 1; src = source; } - else if( fchar == internal_s ) + else if( fchar == source_s ) { if(saw_decimal_point) { @@ -905,7 +930,7 @@ ftime_replace(char *dest, char const * const dest_end, src = ftime + OFFSET_TO_SECOND; } } - else if( fchar == internal_W ) + else if( fchar == source_W ) { ncount = 3; src = ftime + OFFSET_TO_WEEK; @@ -951,12 +976,12 @@ ftime_replace(char *dest, char const * const dest_end, extern "C" void __gg__abs(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ABS - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); @@ -973,22 +998,22 @@ __gg__abs(cblc_field_t *dest, extern "C" void __gg__acos( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ACOS - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value < -1.00Q || value > +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.00) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = acosf128(value); + value = FP128_FUNC(acos)(value); } __gg__float128_to_field( dest, @@ -1000,21 +1025,21 @@ __gg__acos( cblc_field_t *dest, extern "C" void __gg__annuity(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { // FUNCTION ANNUITY - _Float128 retval = 0; + GCOB_FP128 retval = 0; - _Float128 val1 = fabsf128(__gg__float128_from_qualified_field(arg1, + GCOB_FP128 val1 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg1, arg1_offset, arg1_size)); - _Float128 val2 = fabsf128(__gg__float128_from_qualified_field(arg2, + GCOB_FP128 val2 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg2, arg2_offset, arg2_size)); if( val2 > 0) @@ -1029,7 +1054,7 @@ __gg__annuity(cblc_field_t *dest, } else { - retval = val1 / (1- powf128( (1+val1), -val2 )); + retval = val1 / (1- FP128_FUNC(pow)( (1+val1), -val2 )); } } else @@ -1045,25 +1070,25 @@ __gg__annuity(cblc_field_t *dest, extern "C" void __gg__asin( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ASIN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value < -1.0Q || value > +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.0) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = asinf128(value); + value = FP128_FUNC(asin)(value); } __gg__float128_to_field( dest, @@ -1075,18 +1100,18 @@ __gg__asin( cblc_field_t *dest, extern "C" void __gg__atan( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ATAN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = atanf128(value); + value = FP128_FUNC(atan)(value); __gg__float128_to_field( dest, value, @@ -1097,7 +1122,7 @@ __gg__atan( cblc_field_t *dest, extern "C" void __gg__byte_length(cblc_field_t *dest, - cblc_field_t */*source*/, + const cblc_field_t */*source*/, size_t /*source_offset*/, size_t source_size) { @@ -1113,7 +1138,7 @@ __gg__byte_length(cblc_field_t *dest, extern "C" void __gg__char( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1131,17 +1156,18 @@ __gg__char( cblc_field_t *dest, source_size)); ordinal /= __gg__power_of_ten(rdigits); int ch = ordinal-1; - memset(dest->data, internal_space, dest->capacity); + charmap_t *charmap = __gg__get_charmap(dest->encoding); + memset(dest->data, charmap->mapped_character(ascii_space), dest->capacity); dest->data[0] = ch; } extern "C" void __gg__combined_datetime(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -1187,16 +1213,16 @@ __gg__concat( cblc_field_t *dest, extern "C" void __gg__cos(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION COS - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = cosf128(value); + value = FP128_FUNC(cos)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1208,12 +1234,14 @@ void __gg__current_date(cblc_field_t *dest) { // FUNCTION CURRENT-DATE - struct timespec tp = {}; - __gg__clock_gettime(CLOCK_REALTIME, &tp); // time_t tv_sec; long tv_nsec + struct cbl_timespec tp = {}; + __gg__clock_gettime(&tp); // time_t tv_sec; long tv_nsec char retval[DATE_STRING_BUFFER_SIZE]; timespec_to_string(retval, tp); - ascii_to_internal_str(retval, strlen(retval)); + __gg__convert_encoding(PTRCAST(char, retval), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); string_to_dest(dest, retval); } @@ -1222,11 +1250,11 @@ void __gg__seconds_past_midnight(cblc_field_t *dest) { // SECONDS-PAST-MIDNIGHT - struct timespec tp = {}; + struct cbl_timespec tp = {}; struct tm tm; __int128 retval=0; - - __gg__clock_gettime(CLOCK_REALTIME, &tp); // time_t tv_sec; long tv_nsec + + __gg__clock_gettime(&tp); // time_t tv_sec; long tv_nsec localtime_r(&tp.tv_sec, &tm); retval += tm.tm_hour; @@ -1246,7 +1274,7 @@ __gg__seconds_past_midnight(cblc_field_t *dest) extern "C" void __gg__date_of_integer(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1272,13 +1300,13 @@ __gg__date_of_integer(cblc_field_t *dest, extern "C" void __gg__date_to_yyyymmdd( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -1303,7 +1331,7 @@ __gg__date_to_yyyymmdd( cblc_field_t *dest, extern "C" void __gg__day_of_integer( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1332,13 +1360,13 @@ __gg__day_of_integer( cblc_field_t *dest, extern "C" void __gg__day_to_yyyyddd( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -1366,7 +1394,8 @@ void __gg__e(cblc_field_t *dest) { // FUNCTION E - static _Float128 e = 2.7182818284590452353602874713526624977572Q; + static GCOB_FP128 e + = GCOB_FP128_LITERAL(2.7182818284590452353602874713526624977572); __gg__float128_to_field(dest, e, truncation_e, @@ -1376,16 +1405,16 @@ __gg__e(cblc_field_t *dest) extern "C" void __gg__exp(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION EXP - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = expf128(value); + value = FP128_FUNC(exp)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1395,16 +1424,16 @@ __gg__exp(cblc_field_t *dest, extern "C" void __gg__exp10(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION EXP10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = powf128(10.0Q, value); + value = FP128_FUNC(pow)(GCOB_FP128_LITERAL(10.0), value); __gg__float128_to_field(dest, value, truncation_e, @@ -1414,7 +1443,7 @@ __gg__exp10(cblc_field_t *dest, extern "C" void __gg__factorial(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1445,39 +1474,49 @@ __gg__factorial(cblc_field_t *dest, extern "C" void __gg__formatted_current_date( cblc_field_t *dest, // Destination string - cblc_field_t *input, // datetime format + const cblc_field_t *input, // datetime format size_t input_offset, size_t input_size) { - // FUNCTION CURRENT-DATE + // FUNCTION FORMATTED-CURRENT-DATE + + cbl_encoding_t from = input->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_from = __gg__get_charmap(from); + charmap_t *charmap_to = __gg__get_charmap(to); + + int dest_space = charmap_to->mapped_character(ascii_space); + int format_Z = charmap_from->mapped_character(ascii_Z); // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; - memset(d, internal_space, dest->capacity); + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; + memset(d, dest_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(input->data+input_offset); - char *format_end = format + input_size; + const char *format = PTRCAST(char, (input->data+input_offset)); + const char *format_end = format + input_size; bool is_zulu = false; - char *p = format; + const char *p = format; while( p < format_end ) { int ch = *p++; - if( ch == internal_Z ) + if( ch == format_Z ) { is_zulu = true; break; } } - struct timespec ts = {}; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + struct cbl_timespec ts = {}; + __gg__clock_gettime(&ts); struct tm tm = {}; +#ifdef HAVE_STRUCT_TM_TM_ZONE tm.tm_zone = "GMT"; +#endif if( is_zulu ) { gmtime_r(&ts.tv_sec, &tm); @@ -1497,44 +1536,51 @@ __gg__formatted_current_date( cblc_field_t *dest, // Destination string ctm.tz_offset = -timezone/60; char achftime[64]; - get_all_time(achftime, ctm); - ftime_replace(d, dend, format, format_end, achftime); + get_all_time(dest, achftime, ctm); + ftime_replace(d, dend, format, format_end, charmap_from, achftime); } extern "C" void __gg__formatted_date(cblc_field_t *dest, // Destination string - cblc_field_t *arg1, // datetime format + const cblc_field_t *arg1, // datetime format size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, // integer date + const cblc_field_t *arg2, // integer date size_t arg2_offset, size_t arg2_size) { // FUNCTION FORMATTED-DATE + cbl_encoding_t from = arg1->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_from = __gg__get_charmap(from); + charmap_t *charmap_to = __gg__get_charmap(to); + + int dest_space = charmap_to->mapped_character(ascii_space); + // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; - memset(d, internal_space, dest->capacity); + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; + memset(d, dest_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(arg1->data+arg1_offset); - char *format_end = format + arg1_size; + char *format = PTRCAST(char, (arg1->data+arg1_offset)); + const char *format_end = format + arg1_size; struct cobol_tm ctm = {}; populate_ctm_from_date(ctm, arg2, arg2_offset, arg2_size); char achftime[64]; - get_all_time(achftime, ctm); + get_all_time(dest, achftime, ctm); if( __gg__exception_code ) { - memset(d, internal_space, dend-d); + memset(d, dest_space, dend-d); } else { - ftime_replace(d, dend, format, format_end, achftime); + ftime_replace(d, dend, format, format_end, charmap_from, achftime); __gg__adjust_dest_size(dest, format_end-format); } } @@ -1542,32 +1588,37 @@ __gg__formatted_date(cblc_field_t *dest, // Destination string extern "C" void __gg__formatted_datetime( cblc_field_t *dest, // Destination string - cblc_field_t *par1, // datetime format + const cblc_field_t *par1, // datetime format size_t par1_o, size_t par1_s, - cblc_field_t *par2, // integer date + const cblc_field_t *par2, // integer date size_t par2_o, size_t par2_s, - cblc_field_t *par3, // numeric time + const cblc_field_t *par3, // numeric time size_t par3_o, size_t par3_s, - cblc_field_t *par4, // optional offset in seconds + const cblc_field_t *par4, // optional offset in seconds size_t par4_o, size_t par4_s ) { // FUNCTION FORMATTED-DATETIME + cbl_encoding_t from = par1->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_from = __gg__get_charmap(from); + charmap_t *charmap_to = __gg__get_charmap(to); + // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; - memset(d, internal_space, dest->capacity); + char *d = PTRCAST(char, (dest->data)); + const char *dend = d + dest->capacity; + memset(d, charmap_from->mapped_character(ascii_space), dest->capacity); // Establish the formatting string: - char *format = (char *)(par1->data+par1_o); + char *format = PTRCAST(char, (par1->data+par1_o)); char *format_end = format + par1_s; - trim_trailing_spaces(format, format_end); - bool is_zulu = is_zulu_format(format, format_end); + trim_trailing_spaces(format, format_end, charmap_from->mapped_character(ascii_space)); + bool is_zulu = is_zulu_format(format, format_end, charmap_from); struct cobol_tm ctm = {}; @@ -1582,14 +1633,14 @@ __gg__formatted_datetime( cblc_field_t *dest, // Destination string } char achftime[64]; - get_all_time(achftime, ctm); + get_all_time(dest, achftime, ctm); if( __gg__exception_code ) { - memset(d, internal_space, dend-d); + memset(d, charmap_to->mapped_character(ascii_space), dend-d); } else { - ftime_replace(d, dend, format, format_end, achftime); + ftime_replace(d, dend, format, format_end, charmap_from, achftime); __gg__adjust_dest_size(dest, format_end-format); } } @@ -1597,29 +1648,38 @@ __gg__formatted_datetime( cblc_field_t *dest, // Destination string extern "C" void __gg__formatted_time( cblc_field_t *dest,// Destination string - cblc_field_t *par1, // datetime format + const cblc_field_t *par1, // datetime format size_t par1_o, size_t par1_s, - cblc_field_t *par2,// numeric time + const cblc_field_t *par2,// numeric time size_t par2_o, size_t par2_s, - cblc_field_t *par4, // optional offset in seconds + const cblc_field_t *par4, // optional offset in seconds size_t par4_o, size_t par4_s) { // FUNCTION FORMATTED-TIME + cbl_encoding_t from = par1->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_from = __gg__get_charmap(from); + charmap_t *charmap_to = __gg__get_charmap(to); + + int dest_space = charmap_to->mapped_character(ascii_space); + // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; - memset(d, internal_space, dest->capacity); + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; + memset(d, dest_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(par1->data+par1_o); + char *format = PTRCAST(char, (par1->data+par1_o)); char *format_end = format + par1_s; - trim_trailing_spaces(format, format_end); - bool is_zulu = is_zulu_format(format, format_end); + trim_trailing_spaces( format, + format_end, + charmap_from->mapped_character(ascii_space)); + bool is_zulu = is_zulu_format(format, format_end, charmap_from); struct cobol_tm ctm = {}; populate_ctm_from_time( ctm, @@ -1636,14 +1696,14 @@ __gg__formatted_time( cblc_field_t *dest,// Destination string } char achftime[64]; - get_all_time(achftime, ctm); + get_all_time(dest, achftime, ctm); if( __gg__exception_code ) { - memset(d, internal_space, dend-d); + memset(d, dest_space, dend-d); } else { - ftime_replace(d, dend, format, format_end, achftime); + ftime_replace(d, dend, format, format_end, charmap_from, achftime); __gg__adjust_dest_size(dest, format_end-format); } } @@ -1651,15 +1711,15 @@ __gg__formatted_time( cblc_field_t *dest,// Destination string extern "C" void __gg__integer(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = floorf128(value); + value = FP128_FUNC(floor)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1669,7 +1729,7 @@ __gg__integer(cblc_field_t *dest, extern "C" void __gg__integer_of_date(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1724,7 +1784,7 @@ __gg__integer_of_date(cblc_field_t *dest, extern "C" void __gg__integer_of_day( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1751,15 +1811,15 @@ __gg__integer_of_day( cblc_field_t *dest, extern "C" void __gg__integer_part( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - _Float128 retval = floorf128(fabsf128(value)); + GCOB_FP128 retval = FP128_FUNC(floor)(FP128_FUNC(fabs)(value)); if( value < 0 ) { @@ -1774,12 +1834,12 @@ __gg__integer_part( cblc_field_t *dest, extern "C" void __gg__fraction_part(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); bool is_negative = false; @@ -1789,7 +1849,7 @@ __gg__fraction_part(cblc_field_t *dest, value = -value; } - _Float128 retval = value - floorf128(value); + GCOB_FP128 retval = value - FP128_FUNC(floor)(value); if( is_negative ) { @@ -1803,13 +1863,13 @@ __gg__fraction_part(cblc_field_t *dest, extern "C" void -__gg__log( cblc_field_t *dest, - cblc_field_t *source, - size_t source_offset, - size_t source_size) +__gg__log(cblc_field_t *dest, + const cblc_field_t *source, + size_t source_offset, + size_t source_size) { // FUNCTION LOG - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1818,7 +1878,7 @@ __gg__log( cblc_field_t *dest, } else { - _Float128 retval = logf128(value); + GCOB_FP128 retval = FP128_FUNC(log)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1828,13 +1888,13 @@ __gg__log( cblc_field_t *dest, extern "C" void -__gg__log10( cblc_field_t *dest, - cblc_field_t *source, - size_t source_offset, - size_t source_size) +__gg__log10(cblc_field_t *dest, + const cblc_field_t *source, + size_t source_offset, + size_t source_size) { // FUNCTION LOG10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1843,7 +1903,7 @@ __gg__log10( cblc_field_t *dest, } else { - _Float128 retval = log10f128(value); + GCOB_FP128 retval = FP128_FUNC(log10)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1862,11 +1922,10 @@ __gg__max(cblc_field_t *dest, || __gg__treeplet_1f[0]->type == FldLiteralA) ) { cblc_field_t *best_field ; - unsigned char *best_location ; - size_t best_length ; + unsigned char *best_location = nullptr ; + size_t best_length = 0 ; int best_attr ; - bool best_move_all ; - bool best_address_of ; + int best_flags ; bool first_time = true; assert(ncount); @@ -1885,8 +1944,7 @@ __gg__max(cblc_field_t *dest, best_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; best_length = __gg__treeplet_1s[i]; best_attr = __gg__treeplet_1f[i]->attr; - best_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - best_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + best_flags = __gg__fourplet_flags[i]; } else { @@ -1894,31 +1952,27 @@ __gg__max(cblc_field_t *dest, unsigned char *candidate_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; size_t candidate_length = __gg__treeplet_1s[i]; int candidate_attr = __gg__treeplet_1f[i]->attr; - bool candidate_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - bool candidate_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + int candidate_flags = __gg__fourplet_flags[i]; int compare_result = __gg__compare_2( candidate_field, candidate_location, candidate_length, candidate_attr, - candidate_move_all, - candidate_address_of, + candidate_flags, best_field, best_location, best_length, best_attr, - best_move_all, - best_address_of, + best_flags, 0); if( compare_result >= 0 ) { - best_field = candidate_field ; - best_location = candidate_location ; - best_length = candidate_length ; - best_attr = candidate_attr ; - best_move_all = candidate_move_all ; - best_address_of = candidate_address_of ; + best_field = candidate_field ; + best_location = candidate_location ; + best_length = candidate_length ; + best_attr = candidate_attr ; + best_flags = candidate_flags ; } } if( !update_refer_state_for_all(state, __gg__treeplet_1f[i]) ) @@ -1929,13 +1983,15 @@ __gg__max(cblc_field_t *dest, } } + __gg__adjust_dest_size(dest, best_length); dest->type = FldAlphanumeric; + assert(best_location); memcpy(dest->data, best_location, best_length); } else { - _Float128 retval; + GCOB_FP128 retval; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -1952,7 +2008,7 @@ __gg__max(cblc_field_t *dest, } else { - _Float128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); + GCOB_FP128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); if( candidate >= retval ) { retval = candidate; @@ -1975,18 +2031,31 @@ __gg__max(cblc_field_t *dest, extern "C" void __gg__lower_case( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { + cbl_encoding_t from = input->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_dest = __gg__get_charmap(to); + size_t dest_length = dest->capacity; size_t source_length = input_size; - memset(dest->data, internal_space, dest_length); - memcpy(dest->data, input->data+input_offset, std::min(dest_length, source_length)); - internal_to_ascii((char *)dest->data, dest_length); + size_t length = std::min(dest_length, source_length); + memset( dest->data, + charmap_dest->mapped_character(ascii_space), + dest_length); + memcpy(dest->data, input->data+input_offset, length); + __gg__convert_encoding_length(PTRCAST(char, dest->data), + length, + from, + DEFAULT_CHARMAP_SOURCE); std::transform(dest->data, dest->data + dest_length, dest->data, - [](unsigned char c) { return std::tolower(c); }); - ascii_to_internal_str((char *)dest->data, dest_length); + [](unsigned char c) { return std::tolower(c); }); + __gg__convert_encoding_length(PTRCAST(char, dest->data), + length, + DEFAULT_CHARMAP_SOURCE, + to); } extern "C" @@ -1996,7 +2065,7 @@ __gg__mean( cblc_field_t *dest, { // FUNCTION MEAN size_t k_count; - _Float128 sum = kahan_summation(ninputs, + GCOB_FP128 sum = kahan_summation(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -2025,7 +2094,8 @@ __gg__median( cblc_field_t *dest, size_t list_size = 1; - _Float128 *the_list = (_Float128 *)malloc(list_size *sizeof(_Float128)); + GCOB_FP128 *the_list = static_cast<GCOB_FP128 *>(malloc(list_size *sizeof(GCOB_FP128))); + massert(the_list); size_t k_count = 0; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2038,9 +2108,11 @@ __gg__median( cblc_field_t *dest, if(k_count >= list_size) { list_size *= 2; - the_list = (_Float128 *)realloc(the_list, list_size *sizeof(_Float128)); + the_list = PTRCAST(GCOB_FP128, realloc(the_list, list_size *sizeof(GCOB_FP128))); + massert(the_list); } + assert(the_list); the_list[k_count] = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); @@ -2054,7 +2126,7 @@ __gg__median( cblc_field_t *dest, } std::sort(the_list, the_list+k_count); - _Float128 retval; + GCOB_FP128 retval; size_t i=k_count/2; if( k_count & 1 ) { @@ -2077,9 +2149,9 @@ __gg__midrange( cblc_field_t *dest, size_t ncount) { // FUNCTION MIDRANGE - _Float128 val; - _Float128 min=0; - _Float128 max=0; + GCOB_FP128 val; + GCOB_FP128 min=0; + GCOB_FP128 max=0; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2106,7 +2178,7 @@ __gg__midrange( cblc_field_t *dest, } } } - _Float128 retval = (min + max)/2.0; + GCOB_FP128 retval = (min + max)/2.0; __gg__float128_to_field(dest, retval, truncation_e, @@ -2123,12 +2195,11 @@ __gg__min(cblc_field_t *dest, if( ( __gg__treeplet_1f[0]->type == FldAlphanumeric || __gg__treeplet_1f[0]->type == FldLiteralA) ) { - cblc_field_t *best_field ; - unsigned char *best_location ; - size_t best_length ; - int best_attr ; - bool best_move_all ; - bool best_address_of ; + cblc_field_t *best_field ; + unsigned char *best_location = nullptr ; + size_t best_length = 0 ; + int best_attr ; + int best_flags ; bool first_time = true; assert(ncount); @@ -2147,8 +2218,7 @@ __gg__min(cblc_field_t *dest, best_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; best_length = __gg__treeplet_1s[i]; best_attr = __gg__treeplet_1f[i]->attr; - best_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - best_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + best_flags = __gg__fourplet_flags[i]; } else { @@ -2156,31 +2226,27 @@ __gg__min(cblc_field_t *dest, unsigned char *candidate_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; size_t candidate_length = __gg__treeplet_1s[i]; int candidate_attr = __gg__treeplet_1f[i]->attr; - bool candidate_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - bool candidate_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + int candidate_flags = __gg__fourplet_flags[i]; int compare_result = __gg__compare_2( candidate_field, candidate_location, candidate_length, candidate_attr, - candidate_move_all, - candidate_address_of, + candidate_flags, best_field, best_location, best_length, best_attr, - best_move_all, - best_address_of, + best_flags, 0); if( compare_result < 0 ) { - best_field = candidate_field ; - best_location = candidate_location ; - best_length = candidate_length ; - best_attr = candidate_attr ; - best_move_all = candidate_move_all ; - best_address_of = candidate_address_of ; + best_field = candidate_field ; + best_location = candidate_location ; + best_length = candidate_length ; + best_attr = candidate_attr ; + best_flags = candidate_flags ; } } if( !update_refer_state_for_all(state, __gg__treeplet_1f[i]) ) @@ -2193,11 +2259,12 @@ __gg__min(cblc_field_t *dest, __gg__adjust_dest_size(dest, best_length); dest->type = FldAlphanumeric; + assert(best_location); memcpy(dest->data, best_location, best_length); } else { - _Float128 retval; + GCOB_FP128 retval; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2214,7 +2281,7 @@ __gg__min(cblc_field_t *dest, } else { - _Float128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); + GCOB_FP128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); if( candidate < retval ) { retval = candidate; @@ -2281,22 +2348,30 @@ __gg__mod(cblc_field_t *dest, static int numval( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { // Returns the one-based character position of a bad character // returns zero if it is okay - char *p = (char *)(input->data + input_offset); - char *pend = p + input_size; + const char *p = PTRCAST(char, (input->data + input_offset)); + const char *pend = p + input_size; int errpos = 0; __int128 retval = 0; int retval_rdigits = 0; + charmap_t *charmap = __gg__get_charmap(input->encoding); + unsigned char decimal_point + = charmap->mapped_character(__gg__get_decimal_point()); + int mapped_0 = charmap->mapped_character(ascii_0); + int mapped_9 = charmap->mapped_character(ascii_9); + int mapped_space = charmap->mapped_character(ascii_space); + int mapped_plus = charmap->mapped_character(ascii_plus); + int mapped_minus = charmap->mapped_character(ascii_minus); + bool saw_digit= false; - char decimal_point = ascii_to_internal(__gg__get_decimal_point()); bool in_fraction = false; bool leading_sign = false; bool is_negative = false; @@ -2323,24 +2398,24 @@ numval( cblc_field_t *dest, case SPACE1: // We tolerate spaces, and expect to end with a sign, digit, // or decimal point: - if( ch == internal_space ) + if( ch == mapped_space ) { continue; } - if( ch == internal_plus ) + if( ch == mapped_plus ) { leading_sign = true; state = SPACE2; break; } - if( ch == internal_minus ) + if( ch == mapped_minus ) { leading_sign = true; is_negative = true; state = SPACE2; break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { saw_digit = true; retval = ch & 0xF; @@ -2359,11 +2434,11 @@ numval( cblc_field_t *dest, case SPACE2: // We tolerate spaces, and expect to end with a digit or decimal point: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { saw_digit = true; retval = ch & 0xF; @@ -2385,7 +2460,7 @@ numval( cblc_field_t *dest, // end with a space, a sign, "DB" or "CR", or the the end of the string // It's a bit complicated - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { saw_digit = true; retval *= 10; @@ -2406,27 +2481,27 @@ numval( cblc_field_t *dest, in_fraction = true; break; } - if( ch == internal_space ) + if( ch == mapped_space ) { state = SPACE3; break; } - if( ch == internal_plus && leading_sign) + if( ch == mapped_plus && leading_sign) { // We are allowed leading or trailing signs, but not both goto done; } - if( ch == internal_minus && leading_sign) + if( ch == mapped_minus && leading_sign) { // We are allowed leading or trailing signs, but not both goto done; } - if( ch == internal_plus ) + if( ch == mapped_plus ) { state = SPACE4; break; } - if( ch == internal_minus ) + if( ch == mapped_minus ) { is_negative = true; state = SPACE4; @@ -2470,26 +2545,26 @@ numval( cblc_field_t *dest, case SPACE3: // We tolerate spaces, or we end with a sign: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch == internal_plus && leading_sign) + if( ch == mapped_plus && leading_sign) { // We are allowed leading or trailing signs, but not both goto done; } - if( ch == internal_minus && leading_sign) + if( ch == mapped_minus && leading_sign) { // We are allowed leading or trailing signs, but not both goto done; } - if( ch == internal_plus ) + if( ch == mapped_plus ) { state = SPACE4; break; } - if( ch == internal_minus ) + if( ch == mapped_minus ) { is_negative = true; state = SPACE4; @@ -2530,7 +2605,7 @@ numval( cblc_field_t *dest, goto done; break; case SPACE4: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } @@ -2572,32 +2647,48 @@ numval( cblc_field_t *dest, static int numval_c( cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) { size_t errcode = 0; - char *pstart = (char *)(src->data+src_offset); + char *pstart = PTRCAST(char, (src->data+src_offset)); char *pend = pstart + src_size; char *p = pstart; - _Float128 retval = 0; + GCOB_FP128 retval = 0; int sign = 0; int rdigits = 0; int rdigit_bump = 0; - unsigned char decimal_point = ascii_to_internal(__gg__get_decimal_point()); - unsigned char decimal_separator = ascii_to_internal(__gg__get_decimal_separator()); + charmap_t *charmap = __gg__get_charmap(src->encoding); + unsigned char decimal_point + = charmap->mapped_character(__gg__get_decimal_point()); + unsigned char decimal_separator + = charmap->mapped_character(__gg__get_decimal_separator()); + int mapped_0 = charmap->mapped_character(ascii_0); + int mapped_9 = charmap->mapped_character(ascii_9); + int mapped_space = charmap->mapped_character(ascii_space); + int mapped_plus = charmap->mapped_character(ascii_plus); + int mapped_minus = charmap->mapped_character(ascii_minus); + int mapped_C = charmap->mapped_character(ascii_C); + int mapped_R = charmap->mapped_character(ascii_R); + int mapped_D = charmap->mapped_character(ascii_D); + int mapped_B = charmap->mapped_character(ascii_B); + int mapped_c = charmap->mapped_character(ascii_c); + int mapped_r = charmap->mapped_character(ascii_r); + int mapped_d = charmap->mapped_character(ascii_d); + int mapped_b = charmap->mapped_character(ascii_b); char *currency_start; char *currency_end; if( crcy ) { - currency_start = (char *)(crcy->data+crcy_offset); + currency_start = PTRCAST(char, (crcy->data+crcy_offset)); currency_end = currency_start + crcy_size; } else @@ -2607,12 +2698,12 @@ numval_c( cblc_field_t *dest, } char *pcurrency = currency_start; // Trim off spaces from the currency: - while( *pcurrency == internal_space && pcurrency < currency_end ) + while( *pcurrency == mapped_space && pcurrency < currency_end ) { pcurrency += 1; } - while( *(currency_end-1) == internal_space && currency_end > currency_start ) + while( *(currency_end-1) == mapped_space && currency_end > currency_start ) { currency_end -= 1; } @@ -2639,11 +2730,12 @@ numval_c( cblc_field_t *dest, { case first_space : // Eat up spaces, if any, and then dispatch on the first non-space: - if( ch != internal_space ) + if( ch != mapped_space ) { // ch can now be a plus, a minus, a digit, or the first character // of the currency string - if( ch == internal_plus || ch == internal_minus ) + if( ch == mapped_plus + || ch == mapped_minus ) { state = first_sign; // Decrement to pointer in order to pick up the character again @@ -2654,7 +2746,7 @@ numval_c( cblc_field_t *dest, state = currency; p -= 1; } - else if( (ch >= internal_0 && ch <= internal_9) + else if( (ch >= mapped_0 && ch <= mapped_9) || ch == decimal_point ) { state = digits; @@ -2674,7 +2766,7 @@ numval_c( cblc_field_t *dest, case first_sign : // We know the character is a plus or a minus: - if( ch == internal_plus ) + if( ch == mapped_plus ) { sign = 1; state = second_space; @@ -2689,14 +2781,14 @@ numval_c( cblc_field_t *dest, case second_space : // Eat up spaces, if any. This segment has to end with a currency or // a digit: - if( ch != internal_space ) + if( ch != mapped_space ) { if( ch == *pcurrency ) { state = currency; p -= 1; } - else if( (ch >= internal_0 && ch <= internal_9) + else if( (ch >= mapped_0 && ch <= mapped_9) || ch == decimal_point ) { state = digits; @@ -2737,9 +2829,9 @@ numval_c( cblc_field_t *dest, case before_digits : // Eat up spaces, if any. This segment has to end with a digit - if( ch != internal_space ) + if( ch != mapped_space ) { - if( (ch >= internal_0 && ch <= internal_9) + if( (ch >= mapped_0 && ch <= mapped_9) || ch == decimal_point ) { state = digits; @@ -2759,7 +2851,7 @@ numval_c( cblc_field_t *dest, case digits : // The only thing allowed here are digits, decimal points, and // decimal separators - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { // We have a digit. rdigits += rdigit_bump; @@ -2792,14 +2884,14 @@ numval_c( cblc_field_t *dest, case after_digits : // after digits, the only valid things are spaces, plus, minus, D, or C - if( ch != internal_space ) + if( ch != charmap->mapped_character(ascii_space) ) { - if( ch == internal_plus - || ch == internal_minus - || ch == internal_D - || ch == internal_d - || ch == internal_C - || ch == internal_c ) + if( ch == mapped_plus + || ch == mapped_minus + || ch == mapped_D + || ch == mapped_d + || ch == mapped_C + || ch == mapped_c ) { state = second_sign; p -= 1; @@ -2811,28 +2903,27 @@ numval_c( cblc_field_t *dest, if( sign ) { // A second sign isn't allowed - state = final_space; errcode = p - pstart; p = pend; } - if( ch == internal_plus ) + if( ch == mapped_plus ) { sign = 1; } - else if( ch == internal_minus ) + else if( ch == mapped_minus ) { sign = -1; } - else if( (ch == internal_D || ch == internal_d) + else if( (ch == mapped_D || ch == mapped_d) && p < pend - && (*p == internal_B || *p == internal_b) ) + && (*p == mapped_B || *p == mapped_b) ) { sign = -1; p += 1; } - else if( (ch == internal_C || ch == internal_c) + else if( (ch == mapped_C || ch == mapped_c) && p < pend - && (*p == internal_R || *p == internal_r) ) + && (*p == mapped_R || *p == mapped_r) ) { sign = -1; p += 1; @@ -2842,7 +2933,7 @@ numval_c( cblc_field_t *dest, case final_space : // There should be only spaces until the end - if( ch == internal_space ) + if( ch == mapped_space ) { continue; } @@ -2879,7 +2970,7 @@ numval_c( cblc_field_t *dest, extern "C" void __gg__numval( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -2893,7 +2984,7 @@ __gg__numval( cblc_field_t *dest, extern "C" void __gg__test_numval(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -2908,10 +2999,10 @@ __gg__test_numval(cblc_field_t *dest, extern "C" void __gg__numval_c( cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) @@ -2928,10 +3019,10 @@ __gg__numval_c( cblc_field_t *dest, extern "C" void __gg__test_numval_c(cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) @@ -2953,19 +3044,16 @@ __gg__test_numval_c(cblc_field_t *dest, extern "C" void __gg__ord(cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t /*input_size*/) { - // We get our input in internal_character form. - char *arg = (char *)(input->data + input_offset); + // FUNCTION ORD + const char *arg = PTRCAST(char, (input->data + input_offset)); // The ORD function takes a single-character string and returns the // ordinal position of that character. - // In ASCII mode, an A is 0x41, so we return 0x42 - // In EBCDIC mode, an A is 0xC1, so we return 0xC2 - size_t retval = (arg[0]&0xFF) + 1; __gg__int128_to_field(dest, retval, @@ -2989,14 +3077,12 @@ __gg__ord_min(cblc_field_t *dest, unsigned char *best_location; size_t best_length; int best_attr; - bool best_move_all; - bool best_address_of ; + int best_flags; unsigned char *candidate_location; size_t candidate_length; int candidate_attr; - bool candidate_move_all; - bool candidate_address_of; + int candidate_flags; for( size_t i=0; i<ninputs; i++ ) { @@ -3014,8 +3100,7 @@ __gg__ord_min(cblc_field_t *dest, best_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; best_length = __gg__treeplet_1s[i]; best_attr = __gg__treeplet_1f[i]->attr; - best_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - best_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + best_flags = __gg__fourplet_flags[i]; } else { @@ -3024,8 +3109,7 @@ __gg__ord_min(cblc_field_t *dest, candidate_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; candidate_length = __gg__treeplet_1s[i]; candidate_attr = __gg__treeplet_1f[i]->attr; - candidate_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - candidate_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + candidate_flags = __gg__fourplet_flags[i]; int compare_result = __gg__compare_2( @@ -3033,14 +3117,12 @@ __gg__ord_min(cblc_field_t *dest, candidate_location, candidate_length, candidate_attr, - candidate_move_all, - candidate_address_of, + candidate_flags, best, best_location, best_length, best_attr, - best_move_all, - best_address_of, + best_flags, 0); if( compare_result < 0 ) { @@ -3049,8 +3131,7 @@ __gg__ord_min(cblc_field_t *dest, best_location = candidate_location; best_length = candidate_length; best_attr = candidate_attr; - best_move_all = candidate_move_all; - best_address_of = candidate_address_of; + best_flags = candidate_flags; } } if( !update_refer_state_for_all(state, __gg__treeplet_1f[i]) ) @@ -3084,14 +3165,12 @@ __gg__ord_max(cblc_field_t *dest, unsigned char *best_location; size_t best_length; int best_attr; - bool best_move_all; - bool best_address_of ; + int best_flags; unsigned char *candidate_location; size_t candidate_length; int candidate_attr; - bool candidate_move_all; - bool candidate_address_of; + int candidate_flags; for( size_t i=0; i<ninputs; i++ ) { @@ -3109,8 +3188,7 @@ __gg__ord_max(cblc_field_t *dest, best_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; best_length = __gg__treeplet_1s[i]; best_attr = __gg__treeplet_1f[i]->attr; - best_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - best_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + best_flags = __gg__fourplet_flags[i]; } else { @@ -3119,8 +3197,7 @@ __gg__ord_max(cblc_field_t *dest, candidate_location = __gg__treeplet_1f[i]->data + __gg__treeplet_1o[i]; candidate_length = __gg__treeplet_1s[i]; candidate_attr = __gg__treeplet_1f[i]->attr; - candidate_move_all = !!(__gg__fourplet_flags[i] & REFER_T_MOVE_ALL); - candidate_address_of = !!(__gg__fourplet_flags[i] & REFER_T_ADDRESS_OF); + candidate_flags = __gg__fourplet_flags[i]; int compare_result = __gg__compare_2( @@ -3128,14 +3205,12 @@ __gg__ord_max(cblc_field_t *dest, candidate_location, candidate_length, candidate_attr, - candidate_move_all, - candidate_address_of, + candidate_flags, best, best_location, best_length, best_attr, - best_move_all, - best_address_of, + best_flags, 0); if( compare_result > 0 ) { @@ -3144,8 +3219,7 @@ __gg__ord_max(cblc_field_t *dest, best_location = candidate_location; best_length = candidate_length; best_attr = candidate_attr; - best_move_all = candidate_move_all; - best_address_of = candidate_address_of; + best_flags = candidate_flags; } } if( !update_refer_state_for_all(state, __gg__treeplet_1f[i]) ) @@ -3170,7 +3244,8 @@ __gg__pi(cblc_field_t *dest) { // FUNCTION PI - static _Float128 pi = 3.141592653589793238462643383279502884Q; + static GCOB_FP128 pi + = GCOB_FP128_LITERAL(3.141592653589793238462643383279502884); __gg__float128_to_field(dest, pi, truncation_e, @@ -3182,10 +3257,10 @@ void __gg__present_value(cblc_field_t *dest, size_t ncount) { - _Float128 discount = 0;; - _Float128 denom = 1; + GCOB_FP128 discount = 0;; + GCOB_FP128 denom = 1; - _Float128 retval = 0; + GCOB_FP128 retval = 0; bool first_time = true; for(size_t i=0; i<ncount; i++) { @@ -3196,19 +3271,19 @@ __gg__present_value(cblc_field_t *dest, if(first_time) { first_time = false; - _Float128 arg1 = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], + GCOB_FP128 arg1 = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); - if( arg1 <= -1.0Q ) + if( arg1 <= GCOB_FP128_LITERAL(-1.0) ) { exception_raise(ec_argument_function_e); break; } - discount = 1.0Q / (1.0Q + arg1); + discount = GCOB_FP128_LITERAL(1.0) / (GCOB_FP128_LITERAL(1.0) + arg1); } else { - _Float128 arg = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], + GCOB_FP128 arg = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); denom *= discount; @@ -3234,9 +3309,9 @@ __gg__range(cblc_field_t *dest, { // FUNCTION RANGE bool first_time = true; - _Float128 val; - _Float128 min; - _Float128 max; + GCOB_FP128 val; + GCOB_FP128 min; + GCOB_FP128 max; assert(ncount > 0); for(size_t i=0; i<ncount; i++) @@ -3264,7 +3339,7 @@ __gg__range(cblc_field_t *dest, } } - _Float128 retval = max - min; + GCOB_FP128 retval = max - min; __gg__float128_to_field(dest, retval, truncation_e, @@ -3274,10 +3349,10 @@ __gg__range(cblc_field_t *dest, extern "C" void __gg__rem(cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_offset, size_t par1_size, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_offset, size_t par2_size) { @@ -3288,15 +3363,15 @@ __gg__rem(cblc_field_t *dest, // The ISO spec says: // ((argument-1) – ((argument-2) * FUNCTION INTEGER-PART ((argument-1) / (argument-2)))) - _Float128 arg1 = __gg__float128_from_qualified_field( par1, + GCOB_FP128 arg1 = __gg__float128_from_qualified_field( par1, par1_offset, par1_size); - _Float128 arg2 = __gg__float128_from_qualified_field( par2, + GCOB_FP128 arg2 = __gg__float128_from_qualified_field( par2, par2_offset, par2_size); - _Float128 intpart; - _Float128 retval; + GCOB_FP128 intpart; + GCOB_FP128 retval; if( arg2 == 0 ) { exception_raise(ec_argument_function_e); @@ -3304,7 +3379,7 @@ __gg__rem(cblc_field_t *dest, } else { - modff128(arg1 / arg2, &intpart); + FP128_FUNC(modf)(arg1 / arg2, &intpart); retval = arg1 - arg2 * intpart; } @@ -3317,13 +3392,18 @@ __gg__rem(cblc_field_t *dest, extern "C" void __gg__trim( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { + cbl_encoding_t from = arg1->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap = __gg__get_charmap(to); + int mapped_space = charmap->mapped_character(ascii_space); + int rdigits; __int128 type = __gg__binary_value_from_qualified_field(&rdigits, arg2, @@ -3337,30 +3417,39 @@ __gg__trim( cblc_field_t *dest, !(dest->attr & intermediate_e) ) { fprintf(stderr, - "We expect the target of a FUNCTION TIME to " + "We expect the target of a FUNCTION TRIM to " "be an intermediate alphanumeric\n"); abort(); } dest->capacity = dest->offset; + // Make a copy of the input: + char *copy = static_cast<char *>(malloc(arg1_size)); + massert(copy); + memcpy(copy, arg1->data+arg1_offset, arg1_size); + + // Convert it to the destination encoding + __gg__convert_encoding_length(copy, arg1_size, from, to); + + // No matter what, we want to find the leftmost non-space and the // rightmost non-space: - char *left = (char *)(arg1->data+arg1_offset); + char *left = copy; char *right = left + arg1_size-1; // Find left and right: the first and last non-spaces while( left <= right ) { - if( *left != internal_space && *right != internal_space ) + if( *left != mapped_space && *right != mapped_space ) { break; } - if( *left == internal_space ) + if( *left == mapped_space ) { left += 1; } - if( *right == internal_space ) + if( *right == mapped_space ) { right -= 1; } @@ -3369,13 +3458,13 @@ __gg__trim( cblc_field_t *dest, { // We want to leave any trailing spaces, so we return 'right' to its // original value: - right = (char *)(arg1->data+arg1_offset) + arg1_size-1; + right = copy + arg1_size-1; } else if( type == TRAILING ) { // We want to leave any leading spaces, so we return 'left' to its // original value: - left = (char *)(arg1->data+arg1_offset); + left = copy; } if( left > right ) @@ -3389,15 +3478,9 @@ __gg__trim( cblc_field_t *dest, size_t ncount = right+1 - left; __gg__adjust_dest_size(dest, ncount); - // Because it's a temporary, we are weakly confident that we can change - // the capacity to match what we want. At this writing, we aren't 100% - // sure of the implications of the run-time capacity not matching what the - // compiler believes the capacity to be at compile-time. But we obviously - // think it'll be okay. - - char *dest_left = (char *)dest->data; + char *dest_left = PTRCAST(char, dest->data); char *dest_right = dest_left + dest->capacity - 1; - char *dest_end = dest_left + dest->capacity; + const char *dest_end = dest_left + dest->capacity; while( dest_left <= dest_right && left <= right ) { @@ -3405,21 +3488,28 @@ __gg__trim( cblc_field_t *dest, } while(dest_left < dest_end) { - *dest_left++ = internal_space; + *dest_left++ = mapped_space; } } +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R static struct random_data *buf = NULL; static char *state = NULL; static const size_t state_len = 256; +#else +static unsigned seed = 0; +#endif extern "C" void __gg__random( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { + int32_t retval_31; + int rdigits; +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R // This creates a thread-safe pseudo-random number generator // using input as the seed @@ -3430,22 +3520,27 @@ __gg__random( cblc_field_t *dest, // This is the very first time through buf = (random_data *)malloc(sizeof(struct random_data)); buf->state = NULL; - state = (char *)malloc(state_len); + state = static_cast<char *>(malloc(state_len)); - struct timespec ts; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + struct cbl_timespec ts; + __gg__clock_gettime(&ts); initstate_r( ts.tv_nsec, state, state_len, buf); } - - int rdigits; int seed = (int)__gg__binary_value_from_qualified_field(&rdigits, input, input_offset, input_size); srandom_r(seed, buf); - int32_t retval_31; random_r(buf, &retval_31); +#else + seed = (unsigned)__gg__binary_value_from_qualified_field(&rdigits, + input, + input_offset, + input_size); + srandom (seed); + retval_31 = random (); +#endif // We are going to convert this to a value between zero and not quite one: double retval = double(retval_31) / double(0x80000000UL); __gg__double_to_target( dest, @@ -3457,6 +3552,8 @@ extern "C" void __gg__random_next(cblc_field_t *dest) { + int32_t retval_31; +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R // The return value is between zero and not quite one if( !buf ) @@ -3464,14 +3561,15 @@ __gg__random_next(cblc_field_t *dest) // This is the very first time through buf = (random_data *)malloc(sizeof(struct random_data)); buf->state = NULL; - state = (char *)malloc(state_len); - struct timespec ts; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + state = static_cast<char *>(malloc(state_len)); + struct cbl_timespec ts; + __gg__clock_gettime(&ts); initstate_r( ts.tv_nsec, state, state_len, buf); } - int32_t retval_31; random_r(buf, &retval_31); - +#else + retval_31 = random (); +#endif // We are going to convert this to a value between zero and not quite one: double retval = double(retval_31) / double(0x80000000UL); __gg__double_to_target( dest, @@ -3482,30 +3580,53 @@ __gg__random_next(cblc_field_t *dest) extern "C" void __gg__reverse(cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { + cbl_encoding_t from = input->encoding; + cbl_encoding_t to = dest->encoding; + size_t dest_length = dest->capacity; size_t source_length = input_size; size_t length = std::min(dest_length, source_length); - memset(dest->data, internal_space, dest_length); + + // Make a copy of the input + char *copy = static_cast<char *>(malloc(length)); + massert(copy); + memcpy(copy, input->data+input_offset, length); + + // Convert the input to the destination encoding + __gg__convert_encoding_length(copy, + length, + from, + to); + + // Set the destination to all spaces + charmap_t *charmap = __gg__get_charmap(to); + memset(dest->data, charmap->mapped_character(ascii_space), dest_length); for(size_t i=0; i<length; i++) { - dest->data[i] = (input->data+input_offset)[source_length-1-i]; + dest->data[i] = copy[source_length-1-i]; } + if( (dest->attr & intermediate_e) ) + { + dest->capacity = std::min(dest_length, source_length); + } + + free(copy); } extern "C" void __gg__sign( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SIGN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); @@ -3532,17 +3653,17 @@ __gg__sign( cblc_field_t *dest, extern "C" void __gg__sin(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SIN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = sinf128(value); + value = FP128_FUNC(sin)(value); __gg__float128_to_field(dest, value, @@ -3553,23 +3674,23 @@ __gg__sin(cblc_field_t *dest, extern "C" void __gg__sqrt( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SQRT - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value <= 0.0Q ) + if( value < GCOB_FP128_LITERAL(0.0) ) { exception_raise(ec_argument_function_e); } else { - value = sqrtf128(value); + value = FP128_FUNC(sqrt)(value); } __gg__float128_to_field(dest, @@ -3584,12 +3705,12 @@ __gg__standard_deviation( cblc_field_t *dest, size_t ninputs) { // FUNCTION STANDARD-DEVIATION - _Float128 retval = variance(ninputs, + GCOB_FP128 retval = variance(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, __gg__fourplet_flags); - retval = sqrtf128(retval); + retval = FP128_FUNC(sqrt)(retval); __gg__float128_to_field(dest, retval, @@ -3604,7 +3725,7 @@ __gg__sum(cblc_field_t *dest, { // FUNCTION SUM size_t k_count; - _Float128 sum = kahan_summation(ninputs, + GCOB_FP128 sum = kahan_summation(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -3619,16 +3740,16 @@ __gg__sum(cblc_field_t *dest, extern "C" void __gg__tan(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION TAN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = tanf128(value); + value = FP128_FUNC(tan)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -3638,7 +3759,7 @@ __gg__tan(cblc_field_t *dest, extern "C" void __gg__test_date_yyyymmdd( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -3648,14 +3769,8 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, source_offset, source_size); int retval; - int dd = yyyymmdd % 100; int mmdd = yyyymmdd % 10000; int mm = mmdd / 100; - int yyyy = yyyymmdd / 10000; - int jy; - int jm; - int jd; - double JD; if( yyyymmdd < 16010000 || yyyymmdd > 99999999 ) { retval = 1; @@ -3666,6 +3781,13 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, } else { + int dd = yyyymmdd % 100; + int yyyy = yyyymmdd / 10000; + int jy; + int jm; + int jd; + double JD; + // If there is something wrong with the number of days per month for a // given year, the Julian Date conversion won't reverse properly. // For example, January 32 will come back as February 1 @@ -3690,7 +3812,7 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, extern "C" void __gg__test_day_yyyyddd( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -3728,18 +3850,31 @@ __gg__test_day_yyyyddd( cblc_field_t *dest, extern "C" void __gg__upper_case( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { + cbl_encoding_t from = input->encoding; + cbl_encoding_t to = dest->encoding; + charmap_t *charmap_dest = __gg__get_charmap(to); + size_t dest_length = dest->capacity; size_t source_length = input_size; - memset(dest->data, internal_space, dest_length); - memcpy(dest->data, input->data+input_offset, std::min(dest_length, source_length)); - internal_to_ascii((char *)dest->data, dest_length); + size_t length = std::min(dest_length, source_length); + memset( dest->data, + charmap_dest->mapped_character(ascii_space), + dest_length); + memcpy(dest->data, input->data+input_offset, length); + __gg__convert_encoding_length(PTRCAST(char, dest->data), + length, + from, + DEFAULT_CHARMAP_SOURCE); std::transform(dest->data, dest->data + dest_length, dest->data, - [](unsigned char c) { return std::toupper(c); }); - ascii_to_internal_str((char *)dest->data, dest_length); + [](unsigned char c) { return std::toupper(c); }); + __gg__convert_encoding_length(PTRCAST(char, dest->data), + length, + DEFAULT_CHARMAP_SOURCE, + to); } extern "C" @@ -3748,7 +3883,7 @@ __gg__variance( cblc_field_t *dest, size_t ncount) { // FUNCTION VARIANCE - _Float128 retval = variance(ncount, + GCOB_FP128 retval = variance(ncount, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -3763,25 +3898,27 @@ extern "C" void __gg__when_compiled(cblc_field_t *dest, size_t tv_sec, long tv_nsec) { - struct timespec tp = {}; + struct cbl_timespec tp = {}; tp.tv_sec = tv_sec; tp.tv_nsec = tv_nsec; char retval[DATE_STRING_BUFFER_SIZE]; timespec_to_string(retval, tp); - ascii_to_internal_str(retval, strlen(retval)); + __gg__convert_encoding(PTRCAST(char, retval), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); string_to_dest(dest, retval); } extern "C" void __gg__year_to_yyyy( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -3802,12 +3939,20 @@ __gg__year_to_yyyy( cblc_field_t *dest, static int -gets_int(int ndigits, char *p, char *pend, int *digits) +gets_int( int ndigits, + const char *p, + const char *pend, + charmap_t *charmap, + int *digits) { // This routine returns the value of the integer at p. If there is something // wrong with the integer, it returns a negative number, the value being the // position (starting at 1) where the problem is. int retval = 0; + + int checked_0 = charmap->mapped_character(ascii_0); + int checked_9 = charmap->mapped_character(ascii_9); + memset(digits, 0xFF, ndigits * sizeof(int)); for(int i=1; i<=ndigits; i++) { @@ -3818,7 +3963,7 @@ gets_int(int ndigits, char *p, char *pend, int *digits) break; } int ch = *p++; - if( ch < internal_0 || ch > internal_9 ) + if( ch < checked_0 || ch > checked_9 ) { // This isn't a digit zero through nine retval = -i; @@ -3833,7 +3978,10 @@ gets_int(int ndigits, char *p, char *pend, int *digits) static int -gets_year(char *p, char *pend, struct cobol_tm &ctm) +gets_year(const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // Populates ctm.YYYY, ctm.days_in_year, and ctm.weeks_in_year, which are // all determined by the YYYY value. @@ -3843,7 +3991,7 @@ gets_year(char *p, char *pend, struct cobol_tm &ctm) int retval = 0; int digits[4]; - int YYYY = gets_int(4, p, pend, digits); + int YYYY = gets_int(4, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] == 0 ) { @@ -3853,10 +4001,6 @@ gets_year(char *p, char *pend, struct cobol_tm &ctm) { return 2; } - if( digits[0] == 0 && digits[1] < 5) - { - return 2; - } if( digits[2] == -1 ) { return 3; @@ -3901,7 +4045,10 @@ gets_year(char *p, char *pend, struct cobol_tm &ctm) static int -gets_month(char *p, char *pend, struct cobol_tm &ctm) +gets_month( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // Populates ctm.MM @@ -3910,7 +4057,7 @@ gets_month(char *p, char *pend, struct cobol_tm &ctm) int digits[2]; int retval = 0; - int MM = gets_int(2, p, pend, digits); + int MM = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 1) { @@ -3948,7 +4095,10 @@ gets_month(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day(char *p, char *pend, struct cobol_tm &ctm) +gets_day( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // Populates ctm.DD, ctm.day_of_week, ctm.week_of_year, ctm.day_of_week @@ -3956,7 +4106,7 @@ gets_day(char *p, char *pend, struct cobol_tm &ctm) int digits[2]; int retval = 0; - int DD = gets_int(2, p, pend, digits); + int DD = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 3) { @@ -3966,48 +4116,45 @@ gets_day(char *p, char *pend, struct cobol_tm &ctm) { return 2; } - if(DD >= 0) + if( DD >= 0 ) { - if( DD >= 0 ) + if( DD == 0) { - if( DD == 0) - { - // If zero, we know we failed at the second '0' in "00" - retval = 2; - } - else if( DD >= 40) + // If zero, we know we failed at the second '0' in "00" + retval = 2; + } + else if( DD >= 40) + { + // 40 or more, then we knew there was trouble at the first digit + retval = 1; + } + else if(ctm.MM == 2 && DD >=30) + { + // It's February, so if we see 3x we know on the 3 that we are in + // error: + retval = 1; + } + else + { + static const int month_days[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; + int days_in_month = month_days[ctm.MM]; + if( ctm.MM == 2 && ctm.days_in_year == 366 ) { - // 40 or more, then we knew there was trouble at the first digit - retval = 1; + days_in_month = 29; } - else if(ctm.MM == 2 && DD >=30) + + if( DD > days_in_month ) { - // It's February, so if we see 3x we know on the 3 that we are in - // error: - retval = 1; + retval = 2; } else { - static const int month_days[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; - int days_in_month = month_days[ctm.MM]; - if( ctm.MM == 2 && ctm.days_in_year == 366 ) - { - days_in_month = 29; - } - - if( DD > days_in_month ) - { - retval = 2; - } - else - { - // We have a good YYYY-MM-DD - ctm.DD = DD; - double JD = YMD_to_JD(ctm.YYYY, ctm.MM, DD); - double JD_Jan0 = YMD_to_JD(ctm.YYYY, 1, 0); - ctm.day_of_year = (int)(JD - JD_Jan0); - ctm.day_of_week = JD_to_DOW(JD); - } + // We have a good YYYY-MM-DD + ctm.DD = DD; + double JD = YMD_to_JD(ctm.YYYY, ctm.MM, DD); + double JD_Jan0 = YMD_to_JD(ctm.YYYY, 1, 0); + ctm.day_of_year = (int)(JD - JD_Jan0); + ctm.day_of_week = JD_to_DOW(JD); } } } @@ -4020,12 +4167,15 @@ gets_day(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day_of_week(char *p, char *pend, struct cobol_tm &ctm) +gets_day_of_week( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // This is just a simple D, for day-of-week. The COBOL spec is that // it be 1 to 7, 1 being Monday int digits[1]; - int day_of_week = gets_int(1, p, pend, digits); + int day_of_week = gets_int(1, p, pend, charmap, digits); if( day_of_week<0 || day_of_week >7) { // The single character at source is no good: @@ -4069,11 +4219,14 @@ gets_day_of_week(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day_of_year(char *p, char *pend, struct cobol_tm &ctm) +gets_day_of_year( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // This is a three-digit day-of-year, 001 through 365,366 int digits[3]; - int DDD = gets_int(3, p, pend, digits); + int DDD = gets_int(3, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 3) { return 1; @@ -4126,11 +4279,14 @@ gets_day_of_year(char *p, char *pend, struct cobol_tm &ctm) static int -gets_week(char *p, char *pend, struct cobol_tm &ctm) +gets_week(const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // This is a two-digit value, 01 through 52,53 int digits[2]; - int ww = gets_int(2, p, pend, digits); + int ww = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 5 ) { return 1; @@ -4166,11 +4322,15 @@ gets_week(char *p, char *pend, struct cobol_tm &ctm) static int -gets_hours(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) +gets_hours( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm, + bool in_offset) { // This is a two-digit value, 01 through 23 int digits[2]; - int hh = gets_int(2, p, pend, digits); + int hh = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 2 ) { @@ -4211,11 +4371,15 @@ gets_hours(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) static int -gets_minutes(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) +gets_minutes( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm, + bool in_offset) { // This is a two-digit value, 01 through 59 int digits[2]; - int mm = gets_int(2, p, pend, digits); + int mm = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 5 ) { return 1; @@ -4249,11 +4413,14 @@ gets_minutes(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) static int -gets_seconds(char *p, char *pend, struct cobol_tm &ctm) +gets_seconds( const char *p, + const char *pend, + charmap_t *charmap, + struct cobol_tm &ctm) { // This is a two-digit value, 01 through 59 int digits[2]; - int ss = gets_int(2, p, pend, digits); + int ss = gets_int(2, p, pend, charmap, digits); if( digits[0] == -1 || digits[0] > 5 ) { return 1; @@ -4279,26 +4446,36 @@ gets_seconds(char *p, char *pend, struct cobol_tm &ctm) static int -gets_nanoseconds(char *f, char *f_end, char *p, char *pend, struct cobol_tm &ctm) +gets_nanoseconds( const char *f, + const char *f_end, + const char *p, + const char *pend, + struct cobol_tm &ctm, + charmap_t *charmap_format, + charmap_t *charmap_source) { // Because nanoseconds digits to the right of the decimal point can vary from // one digit to our implementation-specific limit of nine characters, this // routine is slightly different. If there is an error, that causes a // positive return value. A negative return value contains the number of - // digits we processed + // digits we processed, + + int format_s = charmap_format->mapped_character(ascii_s); + int source_0 = charmap_source->mapped_character(ascii_0); + int source_9 = charmap_source->mapped_character(ascii_9); int errpos = 0; int ncount = 0; int nanoseconds = 0; - char *pinit = p; - while( f < f_end && *f == internal_s && p < pend ) + const char *pinit = p; + while( f < f_end && *f == format_s && p < pend ) { f += 1; int ch = *p++; errpos += 1; - if( ch < internal_0 || ch > internal_9 ) + if( ch < source_0 || ch > source_9 ) { // Let our caller know we see a bad character return errpos; @@ -4323,24 +4500,44 @@ gets_nanoseconds(char *f, char *f_end, char *p, char *pend, struct cobol_tm &ctm static int fill_cobol_tm(cobol_tm &ctm, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_offset, size_t par1_size, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_offset, size_t par2_size) { // Establish the formatting string: - char *format = (char *)(par1->data+par1_offset); + char *format = PTRCAST(char, (par1->data+par1_offset)); char *format_end = format + par1_size; // Establish the string to be checked: - char *source = (char *)(par2->data+par2_offset); + char *source = PTRCAST(char, (par2->data+par2_offset)); char *source_end = source + par2_size; + charmap_t *charmap_format = __gg__get_charmap(par1->encoding); + charmap_t *charmap_checked = __gg__get_charmap(par2->encoding); + int checked_space = charmap_checked->mapped_character(ascii_space); + int format_space = charmap_format->mapped_character(ascii_space); + int format_T = charmap_format->mapped_character(ascii_T ); + int format_colon = charmap_format->mapped_character(ascii_colon ); + int format_plus = charmap_format->mapped_character(ascii_plus ); + int format_minus = charmap_format->mapped_character(ascii_minus ); + int format_W = charmap_format->mapped_character(ascii_W ); + int format_Z = charmap_format->mapped_character(ascii_Z ); + int format_z = charmap_format->mapped_character(ascii_z ); + int format_s = charmap_format->mapped_character(ascii_s ); + int format_m = charmap_format->mapped_character(ascii_m ); + int format_h = charmap_format->mapped_character(ascii_h ); + int format_w = charmap_format->mapped_character(ascii_w ); + int format_Y = charmap_format->mapped_character(ascii_Y ); + int format_M = charmap_format->mapped_character(ascii_M ); + int format_D = charmap_format->mapped_character(ascii_D ); + int format_zero = charmap_format->mapped_character(ascii_zero ); + // Let's eliminate trailing spaces... - trim_trailing_spaces(format, format_end); - trim_trailing_spaces(source, source_end); + trim_trailing_spaces(format, format_end, format_space); + trim_trailing_spaces(source, source_end, checked_space); bool in_offset = false; bool in_nanoseconds = false; @@ -4359,10 +4556,10 @@ fill_cobol_tm(cobol_tm &ctm, { char ch = *format; - if( ch == internal_T - || ch == internal_colon - || ch == internal_minus - || ch == internal_W) + if( ch == format_T + || ch == format_colon + || ch == format_minus + || ch == format_W) { // These are just formatting characters. They need to be duplicated, // but are otherwise ignored. @@ -4374,34 +4571,34 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_plus ) + if( ch == format_plus ) { // This flags a following hhmm offset. It needs to match a '+' or '-' - if( *source != internal_plus - && *source != internal_minus - && *source != internal_zero) + if( *source != format_plus + && *source != format_minus + && *source != format_zero) { break; } - if( *source == internal_zero ) + if( *source == format_zero ) { // The next four characters have to be zeroes - if( source[1] != internal_zero ) + if( source[1] != format_zero ) { retval += 1; break; } - if( source[2] != internal_zero ) + if( source[2] != format_zero ) { retval += 2; break; } - if( source[3] != internal_zero ) + if( source[3] != format_zero ) { retval += 3; break; } - if( source[4] != internal_zero ) + if( source[4] != format_zero ) { retval += 4; break; @@ -4425,9 +4622,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_Y ) + if( ch == format_Y ) { - errpos = gets_year(source, source_end, ctm); + errpos = gets_year(source, source_end, charmap_checked, ctm); if( errpos > 0 ) { retval += errpos - 1; @@ -4437,9 +4634,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_M ) + if( ch == format_M ) { - errpos = gets_month(source, source_end, ctm); + errpos = gets_month(source, source_end, charmap_checked, ctm); if( errpos > 0 ) { retval += errpos - 1; @@ -4449,13 +4646,13 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_D ) + if( ch == format_D ) { // We have three possibilities: DDD, DD, and D - if( format[1] != internal_D ) + if( format[1] != format_D ) { // A singleton 'D' is a day-of-week - errpos = gets_day_of_week(source, source_end, ctm); + errpos = gets_day_of_week(source, source_end, charmap_checked, ctm); if( errpos > 0) { retval += errpos - 1; @@ -4463,10 +4660,10 @@ fill_cobol_tm(cobol_tm &ctm, } bump = 1; } - else if( format[2] != internal_D ) + else if( format[2] != format_D ) { // This is DD, for day-of-month - errpos = gets_day(source, source_end, ctm); + errpos = gets_day(source, source_end, charmap_checked, ctm); if( errpos > 0) { retval += errpos - 1; @@ -4478,7 +4675,7 @@ fill_cobol_tm(cobol_tm &ctm, { // Arriving here means that it is DDD, for day-of-year // This is DD, for day-of-month - errpos = gets_day_of_year(source, source_end, ctm); + errpos = gets_day_of_year(source, source_end, charmap_checked, ctm); if( errpos > 0) { retval += errpos - 1; @@ -4489,9 +4686,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_w ) + if( ch == format_w ) { - errpos = gets_week(source, source_end, ctm); + errpos = gets_week(source, source_end, charmap_checked, ctm); if( errpos > 0 ) { retval += errpos - 1; @@ -4501,9 +4698,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_h ) + if( ch == format_h ) { - errpos = gets_hours(source, source_end, ctm, in_offset); + errpos = gets_hours(source, source_end, charmap_checked, ctm, in_offset); if( errpos > 0 ) { retval += errpos - 1; @@ -4513,9 +4710,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_m ) + if( ch == format_m ) { - errpos = gets_minutes(source, source_end, ctm, in_offset); + errpos = gets_minutes(source, source_end, charmap_checked, ctm, in_offset); if( errpos > 0 ) { retval += errpos - 1; @@ -4525,9 +4722,9 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_s && !in_nanoseconds ) + if( ch == format_s && !in_nanoseconds ) { - errpos = gets_seconds(source, source_end, ctm); + errpos = gets_seconds(source, source_end, charmap_checked, ctm); if( errpos > 0 ) { retval += errpos - 1; @@ -4537,10 +4734,16 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_s && in_nanoseconds ) + if( ch == format_s && in_nanoseconds ) { // Peel off digits to the right of the decimal point one at a time - errpos = gets_nanoseconds(format, format_end, source, source_end, ctm); + errpos = gets_nanoseconds(format, + format_end, + source, + source_end, + ctm, + charmap_format, + charmap_checked); if( errpos > 0 ) { retval += errpos - 1; @@ -4550,7 +4753,7 @@ fill_cobol_tm(cobol_tm &ctm, goto proceed; } - if( ch == internal_Z || ch == internal_z ) + if( ch == format_Z || ch == format_z ) { // This has to be the end of the road if( std::toupper((unsigned char)source[0]) != 'Z' ) @@ -4585,10 +4788,10 @@ proceed: extern "C" void __gg__test_formatted_datetime(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) @@ -4608,10 +4811,10 @@ __gg__test_formatted_datetime(cblc_field_t *dest, extern "C" void __gg__integer_of_formatted_date(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -4643,10 +4846,10 @@ __gg__integer_of_formatted_date(cblc_field_t *dest, extern "C" void __gg__seconds_from_formatted_time(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -4671,25 +4874,26 @@ __gg__seconds_from_formatted_time(cblc_field_t *dest, extern "C" void __gg__hex_of(cblc_field_t *dest, - cblc_field_t *field, + const cblc_field_t *field, size_t field_offset, size_t field_size) { + charmap_t *charmap = __gg__get_charmap(dest->encoding); static const char hex[17] = "0123456789ABCDEF"; size_t bytes = field_size; __gg__adjust_dest_size(dest, 2*bytes); for(size_t i=0; i<bytes; i++) { unsigned char byte = (field->data+field_offset)[i]; - dest->data[2*i] = ascii_to_internal(hex[byte>>4]); - dest->data[2*i+1] = ascii_to_internal(hex[byte&0xF]); + dest->data[2*i ] = charmap->mapped_character(hex[byte>>4]); + dest->data[2*i+1] = charmap->mapped_character(hex[byte&0xF]); } } extern "C" void __gg__highest_algebraic(cblc_field_t *dest, - cblc_field_t *var, + const cblc_field_t *var, size_t, size_t) { @@ -4731,7 +4935,7 @@ __gg__highest_algebraic(cblc_field_t *dest, extern "C" void __gg__lowest_algebraic( cblc_field_t *dest, - cblc_field_t *var, + const cblc_field_t *var, size_t, size_t) { @@ -4793,10 +4997,21 @@ __gg__lowest_algebraic( cblc_field_t *dest, } static int -floating_format_tester(char const * const f, char * const f_end) +floating_format_tester( char const * const f, + char const * const f_end, + cbl_encoding_t encoding) { + charmap_t *charmap = __gg__get_charmap(encoding); + int mapped_space = charmap->mapped_character(ascii_space); + int mapped_plus = charmap->mapped_character(ascii_plus); + int mapped_minus = charmap->mapped_character(ascii_minus); + int mapped_0 = charmap->mapped_character(ascii_0); + int mapped_9 = charmap->mapped_character(ascii_9); + int mapped_E = charmap->mapped_character(ascii_E); + int mapped_e = charmap->mapped_character(ascii_e); + int decimal_point = charmap->mapped_character(__gg__get_decimal_point()); + int retval = -1; - char decimal_point = __gg__get_decimal_point(); enum { @@ -4817,18 +5032,18 @@ floating_format_tester(char const * const f, char * const f_end) switch(state) { case SPACE1: - if( ch == internal_space ) + if( ch == mapped_space ) { // Just keep looking break; } - if( ch == internal_minus - || ch == internal_plus) + if( ch == mapped_minus + || ch == mapped_plus) { state = SPACE2; break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { state = DIGITS1; break; @@ -4843,11 +5058,11 @@ floating_format_tester(char const * const f, char * const f_end) break; case SPACE2: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { state = DIGITS1; break; @@ -4861,7 +5076,7 @@ floating_format_tester(char const * const f, char * const f_end) break; case DIGITS1: - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { break; } @@ -4870,7 +5085,7 @@ floating_format_tester(char const * const f, char * const f_end) state = DIGITS2; break; } - if( ch == internal_space ) + if( ch == mapped_space ) { state = SPACE3; break; @@ -4879,16 +5094,16 @@ floating_format_tester(char const * const f, char * const f_end) break; case DIGITS2: - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { break; } - if( ch == internal_space ) + if( ch == mapped_space ) { state = SPACE3; break; } - if( ch == internal_E || ch == internal_e ) + if( ch == mapped_E || ch == mapped_e ) { state = SPACE4; break; @@ -4897,16 +5112,16 @@ floating_format_tester(char const * const f, char * const f_end) break; case SPACE3: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { retval = index; break; } - if( ch == internal_E || ch == internal_e ) + if( ch == mapped_E || ch == mapped_e ) { state = SPACE4; break; @@ -4915,16 +5130,16 @@ floating_format_tester(char const * const f, char * const f_end) break; case SPACE4: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch == internal_minus || ch == internal_plus ) + if( ch == mapped_minus || ch == mapped_plus ) { state = SPACE5; break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { state = DIGITS3; break; @@ -4933,11 +5148,11 @@ floating_format_tester(char const * const f, char * const f_end) break; case SPACE5: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { state = DIGITS3; break; @@ -4946,11 +5161,11 @@ floating_format_tester(char const * const f, char * const f_end) break; case DIGITS3: - if( ch >= internal_0 && ch <= internal_9 ) + if( ch >= mapped_0 && ch <= mapped_9 ) { break; } - if( ch == internal_space ) + if( ch == mapped_space ) { state = SPACE6; break; @@ -4959,7 +5174,7 @@ floating_format_tester(char const * const f, char * const f_end) break; case SPACE6: - if( ch == internal_space ) + if( ch == mapped_space ) { break; } @@ -4981,15 +5196,19 @@ floating_format_tester(char const * const f, char * const f_end) extern "C" void __gg__numval_f( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { - _Float128 value = 0; - char *data = (char * )(source->data + source_offset); - char *data_end = data + source_size; + GCOB_FP128 value = 0; + const char *data = PTRCAST(char, (source->data + source_offset)); + const char *data_end = data + source_size; + charmap_t *charmap = __gg__get_charmap(source->encoding); + int mapped_space = charmap->mapped_character(ascii_space); - int error = floating_format_tester(data, data_end); + int error = floating_format_tester( data, + data_end, + source->encoding); if( error || source_size >= 256 ) { @@ -5003,13 +5222,13 @@ __gg__numval_f( cblc_field_t *dest, while( data < data_end ) { char ch = *data++; - if( ch != internal_space ) + if( ch != mapped_space ) { *p++ = ch; } } *p++ = '\0'; - value = strtof128(ach, NULL); + value = strtofp128(ach, NULL); } __gg__float128_to_field(dest, value, @@ -5020,14 +5239,16 @@ __gg__numval_f( cblc_field_t *dest, extern "C" void __gg__test_numval_f(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { - char *data = (char * )(source->data + source_offset); - char *data_end = data + source_size; + const char *data = PTRCAST(char, (source->data + source_offset)); + const char *data_end = data + source_size; - int error = floating_format_tester(data, data_end); + int error = floating_format_tester( data, + data_end, + source->encoding); __gg__int128_to_field(dest, error, @@ -5037,7 +5258,7 @@ __gg__test_numval_f(cblc_field_t *dest, } static bool -ismatch(char *a1, char *a2, char *b1, char *b2) +ismatch(const char *a1, const char *a2, const char *b1, const char *b2) { bool retval = true; while( a1 < a2 && b1 < b2 ) @@ -5051,7 +5272,7 @@ ismatch(char *a1, char *a2, char *b1, char *b2) } static bool -iscasematch(char *a1, char *a2, char *b1, char *b2) +iscasematch(const char *a1, const char *a2, const char *b1, const char *b2) { bool retval = true; while( a1 < a2 && b1 < b2 ) @@ -5064,11 +5285,15 @@ iscasematch(char *a1, char *a2, char *b1, char *b2) return retval; } -static char * -strstr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strstr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(ismatch(haystack, haystack_e, needle, needle_e)) @@ -5081,11 +5306,15 @@ strstr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strcasestr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strcasestr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(iscasematch(haystack, haystack_e, needle, needle_e)) @@ -5098,11 +5327,15 @@ strcasestr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strlaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strlaststr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(ismatch(haystack, haystack_e, needle, needle_e)) @@ -5114,11 +5347,15 @@ strlaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strcaselaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strcaselaststr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(iscasematch(haystack, haystack_e, needle, needle_e)) @@ -5132,13 +5369,13 @@ strcaselaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) extern "C" -void __gg__substitute(cblc_field_t *dest, - cblc_field_t *arg1_f, - size_t arg1_o, - size_t arg1_s, - size_t N, - uint8_t *control - ) +void +__gg__substitute( cblc_field_t *dest, + const cblc_field_t *arg1_f, + size_t arg1_o, + size_t arg1_s, + size_t N, + const uint8_t *control) { // arg2 is the Group 1 triplet. // arg3 is the Group 2 triplet @@ -5146,19 +5383,22 @@ void __gg__substitute(cblc_field_t *dest, size_t *arg2_o = __gg__treeplet_1o; size_t *arg2_s = __gg__treeplet_1s; cblc_field_t **arg3_f = __gg__treeplet_2f; - size_t *arg3_o = __gg__treeplet_2o; - size_t *arg3_s = __gg__treeplet_2s; + const size_t *arg3_o = __gg__treeplet_2o; + const size_t *arg3_s = __gg__treeplet_2s; - ssize_t retval_size = 256; - char *retval = (char *)malloc(retval_size); + ssize_t retval_size; + retval_size = 256; + char *retval = static_cast<char *>(malloc(retval_size)); + massert(retval); *retval = '\0'; - char *haystack = (char *)(arg1_f->data + arg1_o); - char *haystack_e = haystack + arg1_s; + const char *haystack = PTRCAST(char, (arg1_f->data + arg1_o)); + const char *haystack_e = haystack + arg1_s; ssize_t outdex = 0; - char **pflasts = (char **)malloc(N * sizeof(char *)); + const char **pflasts = static_cast<const char **>(malloc(N * sizeof(char *))); + massert(pflasts); if( arg1_s == 0 ) { @@ -5179,15 +5419,15 @@ void __gg__substitute(cblc_field_t *dest, { pflasts[i] = strcasestr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else if( control[i] & substitute_last_e) { pflasts[i] = strcaselaststr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else { @@ -5200,15 +5440,15 @@ void __gg__substitute(cblc_field_t *dest, { pflasts[i] = strstr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else if( control[i] & substitute_last_e) { pflasts[i] = strlaststr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else { @@ -5228,7 +5468,8 @@ void __gg__substitute(cblc_field_t *dest, > retval_size ) { retval_size *= 2; - retval = (char *)realloc(retval, retval_size); + retval = static_cast<char *>(realloc(retval, retval_size)); + massert(retval); } // We checked earlier for FIRST/LAST matches @@ -5243,8 +5484,8 @@ void __gg__substitute(cblc_field_t *dest, continue; } - char *needle = (char *)(arg2_f[i]->data+arg2_o[i]); - char *needle_e = (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]; + const char *needle = PTRCAST(char, arg2_f[i]->data+arg2_o[i]); + const char *needle_e = PTRCAST(char, arg2_f[i]->data+arg2_o[i]) + arg2_s[i]; matched = (control[i] & substitute_anycase_e) && iscasematch( haystack, haystack_e, @@ -5272,7 +5513,8 @@ void __gg__substitute(cblc_field_t *dest, while( outdex + 1 > retval_size ) { retval_size *= 2; - retval = (char *)realloc(retval, retval_size); + retval = static_cast<char *>(realloc(retval, retval_size)); + massert(retval); } retval[outdex++] = *haystack++; } @@ -5289,13 +5531,13 @@ void __gg__substitute(cblc_field_t *dest, extern "C" void __gg__locale_compare( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t arg1_s, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_o, size_t arg2_s, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/ ) @@ -5339,17 +5581,19 @@ __gg__locale_compare( cblc_field_t *dest, } __gg__adjust_dest_size(dest, 1); - ascii_to_internal_str(achretval, 1); dest->data[0] = *achretval; + __gg__convert_encoding(PTRCAST(char, dest->data), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); } extern "C" void __gg__locale_date(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t /*arg1_s*/, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) { @@ -5375,17 +5619,19 @@ __gg__locale_date(cblc_field_t *dest, } __gg__adjust_dest_size(dest, strlen(ach)); - ascii_to_internal_str(ach, strlen(ach)); + __gg__convert_encoding(PTRCAST(char, dest->data), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); memcpy(dest->data, ach, strlen(ach)); } extern "C" void __gg__locale_time(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t /*arg1_s*/, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) @@ -5411,17 +5657,19 @@ __gg__locale_time(cblc_field_t *dest, } __gg__adjust_dest_size(dest, strlen(ach)); - ascii_to_internal_str(ach, strlen(ach)); + __gg__convert_encoding(PTRCAST(char, dest->data), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); memcpy(dest->data, ach, strlen(ach)); } extern "C" void __gg__locale_time_from_seconds( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t arg1_s, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) { @@ -5437,7 +5685,7 @@ __gg__locale_time_from_seconds( cblc_field_t *dest, // Default locale tm tm = {}; - int rdigits; + int rdigits=0; long seconds = (long)__gg__binary_value_from_qualified_field(&rdigits, arg1, arg1_o, @@ -5449,6 +5697,8 @@ __gg__locale_time_from_seconds( cblc_field_t *dest, } __gg__adjust_dest_size(dest, strlen(ach)); - ascii_to_internal_str(ach, strlen(ach)); + __gg__convert_encoding(PTRCAST(char, dest->data), + DEFAULT_CHARMAP_SOURCE, + dest->encoding); memcpy(dest->data, ach, strlen(ach)); } |