From 5612b015920f08249f792b4e40f8f3c92be70b12 Mon Sep 17 00:00:00 2001 From: Bob Dubner <rdubner@symas.com> Date: Thu, 21 Dec 2023 16:37:05 -0500 Subject: [PATCH] LOCALE-COMPARE, -DATE, -TIME, and -TIME-FROM-SECONDS --- gcc/cobol/parse.y | 18 +++-- libgcobol/intrinsic.cc | 147 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 8 deletions(-) diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 4c142c3362c4..f07024250e9f 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -8851,7 +8851,8 @@ intrinsic_locale: { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); - if( ! intrinsic_call_2($$, LOCALE_COMPARE, $r1, $r2) ) YYERROR; + cbl_refer_t dummy = {}; + if( ! intrinsic_call_3($$, LOCALE_COMPARE, $r1, $r2, &dummy) ) YYERROR; } | LOCALE_COMPARE '(' varg[r1] varg[r2] varg[r3] ')' { @@ -8864,9 +8865,10 @@ intrinsic_locale: { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); - if( ! intrinsic_call_1($$, LOCALE_DATE, $r1) ) YYERROR; + cbl_refer_t dummy = {}; + if( ! intrinsic_call_2($$, LOCALE_DATE, $r1, &dummy) ) YYERROR; } - | LOCALE_DATE '(' varg[r1] varg[r2] ')' + | LOCALE_DATE '(' varg[r1] varg[r2] ')' { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); @@ -8876,9 +8878,10 @@ intrinsic_locale: { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); - if( ! intrinsic_call_1($$, LOCALE_TIME, $r1) ) YYERROR; + cbl_refer_t dummy = {}; + if( ! intrinsic_call_2($$, LOCALE_TIME, $r1, &dummy) ) YYERROR; } - | LOCALE_TIME '(' varg[r1] varg[r2] ')' + | LOCALE_TIME '(' varg[r1] varg[r2] ')' { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); @@ -8888,9 +8891,10 @@ intrinsic_locale: { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); - if( ! intrinsic_call_1($$, LOCALE_TIME_FROM_SECONDS, $r1) ) YYERROR; + cbl_refer_t dummy = {}; + if( ! intrinsic_call_2($$, LOCALE_TIME_FROM_SECONDS, $r1, &dummy) ) YYERROR; } - | LOCALE_TIME_FROM_SECONDS '(' varg[r1] varg[r2] ')' + | LOCALE_TIME_FROM_SECONDS '(' varg[r1] varg[r2] ')' { location_set(@1); $$ = new_alphanumeric($r1->field->data.capacity); diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc index d8ca2eed95cc..744fce55517d 100644 --- a/libgcobol/intrinsic.cc +++ b/libgcobol/intrinsic.cc @@ -42,6 +42,8 @@ #include <math.h> #include <algorithm> #include <cctype> +#include <langinfo.h> + #include "libgcobol.h" #include "intrinsic.h" @@ -4874,7 +4876,150 @@ void __gg__substitute(cblc_field_t *dest, __gg__adjust_dest_size(dest, outdex); memcpy(dest->data, retval, outdex); - free(pflasts); free(retval); } + +extern "C" +void +__gg__locale_compare( cblc_field_t *dest, + cblc_refer_t *arg1, + cblc_refer_t *arg2, + cblc_refer_t *arg_locale) + { + char achretval[2] = "?"; + + if( arg_locale && arg_locale->field ) + { + // We don't yet know what to do with a locale + exception_raise(ec_locale_missing_e); + } + else + { + // Default locale + achretval[0] = '='; + size_t length = std::min(arg1->qual_size, arg2->qual_size); + for(size_t i=0; i<length; i++ ) + { + if( arg1->qual_data[i] < arg2->qual_data[i] ) + { + achretval[0] = '<'; + break; + } + if( arg1->qual_data[i] > arg2->qual_data[i] ) + { + achretval[0] = '>'; + break; + } + } + if( achretval[0] == '=' ) + { + if( arg1->qual_size < arg2->qual_size ) + { + achretval[0] = '<'; + } + else if( arg1->qual_size > arg2->qual_size ) + { + achretval[0] = '>'; + } + } + } + + __gg__adjust_dest_size(dest, 1); + ascii_to_internal_str(achretval, 1); + dest->data[0] = *achretval; + } + +extern "C" +void +__gg__locale_date(cblc_field_t *dest, + cblc_refer_t *arg1, + cblc_refer_t *arg_locale) + { + char ach[256] = " "; + + if( arg_locale && arg_locale->field ) + { + // We don't yet know what to do with a locale + exception_raise(ec_locale_missing_e); + } + else + { + // Default locale + tm tm; + memcpy(ach, arg1->qual_data, 8); + ach[8] = '\0'; + long ymd = atoi(ach); + tm.tm_year = ymd/10000 - 1900; + tm.tm_mon = ymd/100 % 100; + tm.tm_mday = ymd % 100; + strcpy(ach, nl_langinfo(D_FMT)); + strftime(ach, sizeof(ach), nl_langinfo(D_FMT), &tm); + } + + __gg__adjust_dest_size(dest, strlen(ach)); + ascii_to_internal_str(ach, strlen(ach)); + memcpy(dest->data, ach, strlen(ach)); + } + +extern "C" +void +__gg__locale_time(cblc_field_t *dest, + cblc_refer_t *arg1, + cblc_refer_t *arg_locale) + { + char ach[256] = " "; + + if( arg_locale && arg_locale->field ) + { + // We don't yet know what to do with a locale + exception_raise(ec_locale_missing_e); + } + else + { + // Default locale + tm tm = {}; + memcpy(ach, arg1->qual_data, 8); + ach[8] = '\0'; + long hms = atoi(ach); + tm.tm_hour = hms/10000; + tm.tm_min = hms/100 % 100; + tm.tm_sec = hms % 100; + strftime(ach, sizeof(ach), nl_langinfo(T_FMT), &tm); + } + + __gg__adjust_dest_size(dest, strlen(ach)); + ascii_to_internal_str(ach, strlen(ach)); + memcpy(dest->data, ach, strlen(ach)); + } + +extern "C" +void +__gg__locale_time_from_seconds( cblc_field_t *dest, + cblc_refer_t *arg1, + cblc_refer_t *arg_locale) + { + char ach[256] = " "; + + if( arg_locale && arg_locale->field ) + { + // We don't yet know what to do with a locale + exception_raise(ec_locale_missing_e); + } + else + { + // Default locale + tm tm = {}; + + int rdigits; + long seconds = (long)__gg__binary_value_from_refer(&rdigits, arg1); + tm.tm_hour = seconds/3600; + tm.tm_min = ((seconds%3600) / 60) % 100; + tm.tm_sec = seconds % 100; + strftime(ach, sizeof(ach), nl_langinfo(T_FMT), &tm); + } + + __gg__adjust_dest_size(dest, strlen(ach)); + ascii_to_internal_str(ach, strlen(ach)); + memcpy(dest->data, ach, strlen(ach)); + } -- GitLab