diff --git a/libgcobol/common-defs.h b/libgcobol/common-defs.h
index 5c35dc78009..f4f4fca1d08 100644
--- a/libgcobol/common-defs.h
+++ b/libgcobol/common-defs.h
@@ -60,7 +60,7 @@
/* COBOL has the concept of Numeric Display values, which use an entire
byte
per digit. IBM also calls this "Zoned Decimal".
-
+
In ASCII, the digits are '0' through '9' (0x30 through 0x39'. Signed
values are indicated by turning on the 0x40 bit in either the first
byte (for LEADING variables) or the last byte (for TRAILING).
@@ -187,49 +187,49 @@ enum cbl_field_type_t {
* (But maybe the fill character should just be an explicit character.)
*/
enum cbl_field_attr_t : uint64_t {
- none_e = 0x0000000000,
- figconst_1_e = 0x0000000001, // This needs to be 1 - don't change
the position
- figconst_2_e = 0x0000000002, // This needs to be 2
- figconst_4_e = 0x0000000004, // This needs to be 4
- rjust_e = 0x0000000008, // justify right
- ljust_e = 0x0000000010, // justify left
- zeros_e = 0x0000000020, // zero fill
- signable_e = 0x0000000040,
- constant_e = 0x0000000080, // pre-assigned constant
- function_e = 0x0000000100,
- quoted_e = 0x0000000200,
- filler_e = 0x0000000400,
- register_e = 0x0000000800, // Data definition is found in
constants.cc
- intermediate_e = 0x0000001000, // Compiler-defined temporary
variable
- embiggened_e = 0x0000002000, // redefined numeric made 64-bit by
USAGE POINTER
- all_alpha_e = 0x0000004000, // FldAlphanumeric, but all A's
- all_x_e = 0x0000008000, // picture is all X's
- all_ax_e = 0x000000a000, // picture is all A's or all X's
- prog_ptr_e = 0x0000010000, // FUNCTION-POINTER or
PROGRAM-POINTER
- scaled_e = 0x0000020000,
- refmod_e = 0x0000040000, // Runtime; indicates a refmod is
active
- based_e = 0x0000080000, // pointer capacity, for ADDRESS OF
or ALLOCATE
- any_length_e = 0x0000100000, // inferred length of linkage in
nested program
- global_e = 0x0000200000, // field has global scope
- external_e = 0x0000400000, // field has external scope
- blank_zero_e = 0x0000800000, // BLANK WHEN ZERO
+ none_e = 0x0000000000,
+ figconst_1_e = 0x0000000001, // This needs to be 1 - don't change
the position
+ figconst_2_e = 0x0000000002, // This needs to be 2
+ figconst_4_e = 0x0000000004, // This needs to be 4
+ rjust_e = 0x0000000008, // justify right
+ ljust_e = 0x0000000010, // justify left
+ zeros_e = 0x0000000020, // zero fill
+ signable_e = 0x0000000040,
+ constant_e = 0x0000000080, // pre-assigned constant
+ function_e = 0x0000000100,
+ quoted_e = 0x0000000200,
+ filler_e = 0x0000000400,
+ register_e = 0x0000000800, // Data definition is found in
constants.cc
+ intermediate_e = 0x0000001000, // Compiler-defined temporary
variable
+ embiggened_e = 0x0000002000, // redefined numeric made 64-bit by
USAGE POINTER
+ all_alpha_e = 0x0000004000, // FldAlphanumeric, but all A's
+ all_x_e = 0x0000008000, // picture is all X's
+ all_ax_e = 0x000000a000, // picture is all A's or all X's
+ prog_ptr_e = 0x0000010000, // FUNCTION-POINTER or
PROGRAM-POINTER
+ scaled_e = 0x0000020000,
+ refmod_e = 0x0000040000, // Runtime; indicates a refmod is
active
+ based_e = 0x0000080000, // pointer capacity, for ADDRESS OF
or ALLOCATE
+ any_length_e = 0x0000100000, // inferred length of linkage in
nested program
+ global_e = 0x0000200000, // field has global scope
+ external_e = 0x0000400000, // field has external scope
+ blank_zero_e = 0x0000800000, // BLANK WHEN ZERO
// data division uses 2 low bits of high byte
- linkage_e = 0x0001000000, // field is in linkage section
- local_e = 0x0002000000, // field is in local section
- leading_e = 0x0004000000, // leading sign (signable_e alone
means trailing)
- separate_e = 0x0008000000, // separate sign
- envar_e = 0x0010000000, // names an environment variable
- encoded_e = 0x0020000000, // data.initial matches
codeset.encoding
- bool_encoded_e = 0x0040000000, // data.initial is a boolean string
- hex_encoded_e = 0x0080000000, // data.initial is a hex-encoded
string
- depends_on_e = 0x0100000000, // A group hierachy contains a
DEPENDING_ON
- initialized_e = 0x0200000000, // Don't call parser_initialize from
parser_symbol_add
- has_value_e = 0x0400000000, // Flag to hierarchical descendents
to ignore .initial
- ieeedec_e = 0x0800000000, // Indicates a FldFloat is IEEE 754
decimal, rather than binary
- big_endian_e = 0x1000000000, // Indicates a value is big-endian
- same_as_e = 0x2000000000, // Field produced by SAME AS (cannot
take new members)
- record_key_e = 0x4000000000,
- typedef_e = 0x8000000000, // IS TYPEDEF
+ linkage_e = 0x0001000000, // field is in linkage section
+ local_e = 0x0002000000, // field is in local section
+ leading_e = 0x0004000000, // leading sign (signable_e alone
means trailing)
+ separate_e = 0x0008000000, // separate sign
+ envar_e = 0x0010000000, // names an environment variable
+ encoded_e = 0x0020000000, // data.initial matches
codeset.encoding
+ bool_encoded_e = 0x0040000000, // data.initial is a boolean string
+ hex_encoded_e = 0x0080000000, // data.initial is a hex-encoded
string
+ depends_on_e = 0x0100000000, // A group hierachy contains a
DEPENDING_ON
+ initialized_e = 0x0200000000, // Don't call parser_initialize from
parser_symbol_add
+ has_value_e = 0x0400000000, // Flag to hierarchical descendents
to ignore .initial
+ ieeedec_e = 0x0800000000, // Indicates a FldFloat is IEEE 754
decimal, rather than binary
+ big_endian_e = 0x1000000000, // Indicates a value is big-endian
+ same_as_e = 0x2000000000, // Field produced by SAME AS (cannot
take new members)
+ record_key_e = 0x4000000000,
+ typedef_e = 0x8000000000, // IS TYPEDEF
strongdef_e = typedef_e + intermediate_e, // STRONG TYPEDEF (not
temporary)
};
// The separate_e value does double-duty for FldPacked/COMP-6, which is
not
@@ -239,7 +239,13 @@ enum cbl_field_attr_t : uint64_t {
// that there is no sign nybble.
#define packed_no_sign_e separate_e
-enum cbl_figconst_t
+#define LOW_VALUE_E figconst_1_e
+#define ZERO_VALUE_E (figconst_2_e|figconst_1_e)
+#define SPACE_VALUE_E figconst_4_e
+#define QUOTE_VALUE_E (figconst_4_e|figconst_1_e)
+#define HIGH_VALUE_E (figconst_4_e|figconst_2_e)
+
+enum cbl_figconst_t : uint64_t
{
normal_value_e = 0, // This one must be zero
low_value_e = 1, // The order is important, because
@@ -431,6 +437,18 @@ enum module_type_t {
module_toplevel_e,
};
+enum convert_type_t {
+ convert_alpha_e = 0x01,
+ convert_nat_e = 0x02,
+ convert_any_e = 0x03, // i.e., both
+ convert_byte_e = 0x04,
+ convert_hex_e = 0x08, // may be combined with alpha or national
+ convert_just_bit_e = 0x10,
+ convert_just_e = 0x18, // combined with HEX
+ convert_rjust_bit_e = 0x20,
+ convert_rjust_e = 0x38, // combined with JUSTIFY
+};
+
/*
* Compare a "raised" EC to an enabled EC or of a declarative. "raised"
may in
* fact not be raised; in the compiler this function is used to compare a
TURN
@@ -490,7 +508,8 @@ struct cbl_declarative_t {
size_t section; // implies program
bool global;
ec_type_t type;
- uint32_t nfile, files[files_max];
+ size_t nfile;
+ uint64_t files[files_max];
cbl_file_mode_t mode;
explicit cbl_declarative_t( cbl_file_mode_t mode = file_mode_none_e )
@@ -544,6 +563,7 @@ struct cbl_declarative_t {
std::vector<uint64_t> encode() const;
/*
+ * Sort file names before file modes, and file modes before non-IO.
* Sort file names before file modes, and file modes before non-IO.
*/
bool operator<( const cbl_declarative_t& that ) const {
@@ -566,7 +586,7 @@ struct cbl_declarative_t {
// TRUE if there are no files to match, or the provided file is in
the list.
bool match_file( size_t file ) const {
- static const uint32_t * pend = files + nfile;
+ static const uint64_t * pend = files + nfile;
return nfile == 0 || pend != std::find(files, files + nfile, file);
}
diff --git a/libgcobol/encodings.h b/libgcobol/encodings.h
index 37bcde305fc..7d92f2d7a0d 100644
--- a/libgcobol/encodings.h
+++ b/libgcobol/encodings.h
@@ -1209,7 +1209,7 @@ valid_encoding( cbl_encoding_t enc ) {
struct encodings_t {
bool supported;
cbl_encoding_t type;
- const char name[32];
+ char name[32];
};
#endif
diff --git a/libgcobol/gcobolio.h b/libgcobol/gcobolio.h
index 14ef069ccb7..064af5bad54 100644
--- a/libgcobol/gcobolio.h
+++ b/libgcobol/gcobolio.h
@@ -123,9 +123,10 @@ typedef struct cblc_file_t
int errnum; // most recent errno; can't
reuse "errno" as the name
file_status_t io_status; // See 2014 standard, section
9.1.12
int padding; // Actually a char
- int delimiter; // ends a record; defaults to
'\n'.
+ uint32_t delimiter; // ends a record; defaults to
'\n'.
+ int stride; // Width of a character
int flags; // cblc_file_flags_t
- int recent_char; // This is the most recent
char sent to the file
+ uint32_t recent_char; // This is the most recent
char sent to the file
int recent_key;
cblc_file_prior_op_t prior_op; // run-time type is INT
cbl_encoding_t encoding; // We assume size int
diff --git a/libgcobol/gfileio.cc b/libgcobol/gfileio.cc
index 7c01f39a8c0..c6813be6ef1 100644
--- a/libgcobol/gfileio.cc
+++ b/libgcobol/gfileio.cc
@@ -190,55 +190,83 @@ handle_errno(cblc_file_t *file, const char
*function, const char *msg)
}
static
-char *
-get_filename( const cblc_file_t *file)
+void
+establish_filename( cblc_file_t *file,
+ const cblc_field_t *field_of_name,
+ char *filename)
{
- bool is_quoted = !!(file->flags & file_name_quoted_e);
+ // This routine sets file->filename to the provided name. The name
might
+ // ultimately be filename, which if present has to be in the system
encoding
+ // and is flagged as not-quoted, meaning that it could have been from
an
+ // environment variable. It could be from a FldLiteral, which for a
SELECT
+ // clause is not encoded in field_of_name->encoding. Or it could be
from a
+ // variable, in which case it is encoded.
- static size_t fname_size = MINIMUM_ALLOCATION_SIZE;
- static char *fname = static_cast<char
*>(malloc(MINIMUM_ALLOCATION_SIZE));
- massert(fname);
- if( strlen(file->filename)+1 > fname_size)
- {
- fname_size = strlen(file->filename)+1 ;
- fname = static_cast<char *>(realloc(fname, fname_size));
- }
+ // Whenever anybody establishes file->filename, it should be done
through
+ // a malloc.
- strcpy(fname, file->filename);
+ // The field_of_name was not encoded in any way. The
field_of_name->codeset
+ // might the same as ordinary alphanumerics, but the field->data for
literals
+ // was not encoded.
- if( !is_quoted )
+ char *allocated_here = nullptr;
+ if( !filename )
{
- // We have been given something that might be the name of an
- // environment variable that contains the filename:
- const char *p_from_environment = getenv(fname);
- if( p_from_environment )
+ // We weren't given a filename, so we extract it from the
field_of_name
+
+ file->flags |= file_name_quoted_e;
+ if( field_of_name->type == FldLiteralA )
{
- if( strlen(p_from_environment)+1 > fname_size )
+ // For literals in SELECT clauses, the initial value is the
+ // nul-terminated filename in the source-code encoding. The
+ // field->encoding is possibly wrong, but irrelevant.
+ allocated_here = static_cast<char
*>(malloc(field_of_name->capacity+1));
+ massert(allocated_here);
+ memcpy(allocated_here, field_of_name->data,
field_of_name->capacity);
+ allocated_here[field_of_name->capacity] = '\0';
+ filename = allocated_here;
+ }
+ else
+ {
+ // We need to convert from the designated encoding to the system
+ // encoding:
+ filename = __gg__iconverter(field_of_name->encoding,
+ __gg__console_encoding,
+ reinterpret_cast<char
*>(field_of_name->data),
+ field_of_name->capacity);
+ // COBOL strings are space-filled to the right, so we have to get
rid
+ // of any spaces out there. If somebody *wants* a filename
space-filled
+ // to the right, well, at this juncture I am not prepared to be
complicit
+ // in that particular flavor of lunacy.
+ size_t n = strlen(filename)-1;
+ // Note the conditional that terminates the loop when n goes from
zero
+ // to a huge positive number in the event that the string is all
SPACES
+ while( n < strlen(filename) && filename[n] == ascii_space )
{
- fname_size = strlen(p_from_environment)+1;
- free(fname);
- fname = static_cast<char *>(malloc(fname_size));
- massert(fname);
+ filename[n--] = '\0';
}
- strcpy(fname, p_from_environment);
}
}
+ else
+ {
+ file->flags &= ~file_name_quoted_e;
+ }
+
+ // At this point, we have a trimmed filename in the system encoding:
- if(*fname)
+ if( !(file->flags & file_name_quoted_e) )
{
- // COBOL strings are space-filled to the right, so we have to get rid
- // of any spaces out there. If somebody *wants* a filename
space-filled
- // to the right, well, at this juncture I am not prepared to be
complicit
- // in that particular flavor of lunacy.
- size_t n = strlen(fname)-1;
- // Note the conditional that terminates the loop when n goes from
zero
- // to a huge positive number in the event that the string is all
SPACES
- while( n < strlen(fname) && fname[n] == ascii_space )
+ // We have been given something that might be the name of an
+ // environment variable that contains the filename:
+ char *p_from_environment = getenv(filename);
+ if( p_from_environment )
{
- fname[n--] = '\0';
+ filename = p_from_environment;
}
}
- return fname;
+ free(file->filename);
+ file->filename = strdup(filename);
+ free(allocated_here);
}
static void
@@ -308,7 +336,7 @@ void
__gg__file_init(
cblc_file_t *file,
const char *name,
- size_t symbol_table_index,
+ uint64_t symbol_table_index,
cblc_field_t **keys,
int *key_numbers,
int *uniques,
@@ -353,6 +381,7 @@ __gg__file_init(
file->errnum = 0 ;
file->io_status = FsSuccess ;
file->delimiter = charmap->mapped_character(ascii_newline)
;
+ file->stride = charmap->stride();
file->flags = file_flag_none_e;
file->flags |= (optional ? file_flag_optional_e :
file_flag_none_e)
+ file_flag_initialized_e;
@@ -666,7 +695,7 @@ relative_file_delete(cblc_file_t *file, bool
is_random)
file->errnum = 0;
file->io_status = FsErrno;
- char record_marker;
+ cbl_char_t record_marker;
unsigned char *stash = static_cast<unsigned char
*>(malloc(file->default_record->capacity));
massert(stash);
@@ -731,6 +760,7 @@ relative_file_delete(cblc_file_t *file, bool
is_random)
errno = 0;
file->errnum = 0;
+ record_marker = 0;
ssize_t presult = pread(rfp.fd, &record_marker, 1,
rfp.flag_position);
if( presult < 0 )
{
@@ -1153,45 +1183,55 @@ __io__file_delete(cblc_file_t *file, bool
is_random)
}
static void
-__io__file_remove(cblc_file_t *file, char *filename, int is_quoted)
+trim_in_place(char *psz)
{
- // filename is the result of a strdup or malloc. Because both FILE
OPEN
- // and FILE DELETE can establish or change a name, we free it here and
- // replace it. The same is true in FILE DELETE Format 2
- free(file->filename);
- file->filename = filename;
- file->flags &= ~file_name_quoted_e;
- file->flags |= is_quoted ? file_name_quoted_e : file_flag_none_e;
- int erc;
-
- // This code copied from reopen
- const char *trimmed_name = get_filename(file);
- if( !trimmed_name[0] )
+ // Get rid of leading spaces:
+ if( *psz == ascii_space )
{
- bool all_spaces = true;
- for(size_t i=0; i<strlen(file->filename); i++)
+ char *p = psz;
+ while(*p++ == ascii_space)
{
- if( file->filename[i] != ascii_space )
- {
- all_spaces = false;
- }
- break;
+ // Just trim them away:
}
- if( all_spaces )
+ p -= 1;
+ size_t i=0;
+ while(*p)
{
- warnx("Warning: %s specified with a filename that is all spaces",
- file->name);
- file->io_status = FsNameError; // "31"
- goto done;
+ psz[i++] = *p++;
}
+ psz[i++] = '\0';
+ }
+ // Get rid of trailing spaces:
+ size_t len = strlen(psz);
+ size_t i = len-1;
+ while( i < len && psz[i] == ascii_space )
+ {
+ psz[i--] = '\0';
+ }
+ }
- warnx( "%s(): There is no environment variable named \"%s\"\n",
- __func__,
- file->filename);
- file->io_status = FsNoFile; // "35"
+static void
+__io__file_remove(cblc_file_t *file,
+ const char *filename)
+ {
+ file->errnum = 0;
+ file->io_status = FsErrno;
+ int erc;
+
+ if( filename )
+ {
+ free(file->filename);
+ file->filename = strdup(filename);
+ trim_in_place(file->filename);
+ }
+
+ if( !strlen(file->filename) )
+ {
+ warnx("Warning: %s specified with a filename that is empty",
+ file->name);
+ file->io_status = FsNameError; // "31"
goto done;
}
- // trimmed_name is now the file system name of the file to be removed.
// If the file is open, we flag that with "41"
if( file->file_pointer )
@@ -1202,7 +1242,7 @@ __io__file_remove(cblc_file_t *file, char *filename,
int is_quoted)
// There's been a lot of buildup. We can now try to remove the file:
errno = 0;
- erc = remove(trimmed_name);
+ erc = remove(file->filename);
if( erc == 0 )
{
// All is copacetic. There was a file, and now it's gone.
@@ -1210,13 +1250,13 @@ __io__file_remove(cblc_file_t *file, char
*filename, int is_quoted)
}
else if( errno == ENOENT )
{
- // The file didn't exist.
+ // The file didn't exist.
file->io_status = FsUnavail; // "05"
}
else
{
// We have some other kind of error. Lack of credentials, or
whatever.
- file->io_status = FsErrno; //
+ file->io_status = FsErrno; //
goto done;
}
@@ -1504,7 +1544,8 @@ relative_file_start(cblc_file_t *file,
while( rfp.record_position >= 0
&& rfp.record_position+total_record_length <= rfp.file_size )
{
- char record_marker;
+ cbl_char_t record_marker;
+ record_marker = 0;
ssize_t presult = pread(rfp.fd, &record_marker, 1,
rfp.flag_position);
if( presult < 0 )
{
@@ -1952,7 +1993,7 @@ relative_file_rewrite( cblc_file_t *file, size_t
length, bool is_random )
{
// This is like a write, except the place we are putting
// it has to be occupied instead of empty.
- char record_marker;
+ cbl_char_t record_marker;
if( relative_file_parameters_get( rfp,
rfm_microfocus_e,
file,
@@ -1963,6 +2004,7 @@ relative_file_rewrite( cblc_file_t *file, size_t
length, bool is_random )
goto done;
}
+ record_marker = 0;
ssize_t presult = pread(rfp.fd, &record_marker, 1,
rfp.flag_position);
if( presult < 0 )
{
@@ -2513,7 +2555,8 @@ relative_file_write(cblc_file_t *file,
}
}
// Let's check to make sure the slot for this record is currently
available:
- char record_marker;
+ cbl_char_t record_marker;
+ record_marker = 0;
ssize_t presult = pread(rfp.fd, &record_marker, 1,
rfp.flag_position);
if( presult < 0 )
{
@@ -2599,9 +2642,11 @@ sequential_file_write(cblc_file_t *file,
{
// This code handles SEQUENTIAL and LINE SEQUENTIAl
charmap_t *charmap = __gg__get_charmap(file->encoding);
+ int stride = charmap->stride();
- char ch = '\0';
- size_t characters_to_write;
+ // ch is the vertical control character
+ cbl_char_t ch = '\0';
+ size_t bytes_to_write;
int lcount;
@@ -2628,13 +2673,13 @@ sequential_file_write(cblc_file_t *file,
}
// By default, we write out the number of characters in the record area
- characters_to_write = length;
+ bytes_to_write = length;
// That gets overridden if there is a record_length
if( file->record_length )
{
int rdigits;
- characters_to_write = (int)__gg__binary_value_from_field(
+ bytes_to_write = stride * (int)__gg__binary_value_from_field(
&rdigits,
file->record_length);
}
@@ -2642,20 +2687,23 @@ sequential_file_write(cblc_file_t *file,
if( file->org == file_line_sequential_e )
{
// If file-sequential, then trailing spaces are removed:
- while( characters_to_write > 0
- && location[characters_to_write-1] ==
charmap->mapped_character(ascii_space) )
+ while(bytes_to_write > 0
+ && charmap->getch(location, bytes_to_write-stride)
+ ==
charmap->mapped_character(ascii_space) )
{
- characters_to_write -= 1;
+ bytes_to_write -= stride;
}
}
- if( after && file->org == file_line_sequential_e && ch ==
charmap->mapped_character(ascii_newline) )
+ if( after && file->org == file_line_sequential_e
+ && ch ==
charmap->mapped_character(ascii_newline) )
{
// In general, we terminate every line with a newline. Because this
// line is supposed to start with a newline, we decrement the line
// counter by one if we had already sent one.
- if( lcount && ( file->recent_char ==
charmap->mapped_character(ascii_newline)
- || file->recent_char ==
charmap->mapped_character(ascii_ff)) )
+ if( lcount &&
+ ( file->recent_char ==
charmap->mapped_character(ascii_newline)
+ || file->recent_char ==
charmap->mapped_character(ascii_ff)) )
{
lcount -= 1;
}
@@ -2665,7 +2713,10 @@ sequential_file_write(cblc_file_t *file,
{
while(lcount--)
{
- fputc(ch, file->file_pointer);
+ fwrite( &ch,
+ stride,
+ 1,
+ file->file_pointer);
if( handle_ferror(file, __func__, "fputc() error [3]") )
{
goto done;
@@ -2679,10 +2730,10 @@ sequential_file_write(cblc_file_t *file,
switch(file->org)
{
case file_line_sequential_e:
- if( characters_to_write )
+ if( bytes_to_write )
{
fwrite( location,
- characters_to_write,
+ bytes_to_write,
1,
file->file_pointer);
if( handle_ferror(file, __func__, "fwrite() error") )
@@ -2694,13 +2745,13 @@ sequential_file_write(cblc_file_t *file,
break;
case file_sequential_e:
- if( characters_to_write )
+ if( bytes_to_write )
{
// File sequential records can start off with a four-byte
// preamble.
- if( characters_to_write < file->record_area_min
- || characters_to_write > file->record_area_max)
+ if( bytes_to_write < file->record_area_min
+ || bytes_to_write > file->record_area_max)
{
file->io_status = FsBoundWrite; // "44"
goto done;
@@ -2709,11 +2760,11 @@ sequential_file_write(cblc_file_t *file,
if( file->record_area_min != file->record_area_max )
{
// Because of the min/max mismatch, we require a preamble:
- // The first two bytes are the big-endian character count
+ // The first two bytes are the big-endian byte count
const unsigned char preamble[4] =
{
- (unsigned char)(characters_to_write>>8),
- (unsigned char)(characters_to_write),
+ (unsigned char)(bytes_to_write>>8),
+ (unsigned char)(bytes_to_write),
0,
0
};
@@ -2729,7 +2780,7 @@ sequential_file_write(cblc_file_t *file,
}
fwrite( location,
- characters_to_write,
+ bytes_to_write,
1,
file->file_pointer);
if( handle_ferror(file, __func__, "fwrite() error") )
@@ -2753,7 +2804,10 @@ sequential_file_write(cblc_file_t *file,
{
// Special case: when AFTER NON-ZERO lines, we stick a newline on
the
// end of this record:
- fputc(ch, file->file_pointer);
+ fwrite( &ch,
+ stride,
+ 1,
+ file->file_pointer);
if( handle_ferror(file, __func__, "fputc() error [4]") )
{
goto done;
@@ -2766,7 +2820,10 @@ sequential_file_write(cblc_file_t *file,
// We did the output BEFORE, so now it's time to send some newlines
while(lcount--)
{
- fputc(ch, file->file_pointer);
+ fwrite( &ch,
+ stride,
+ 1,
+ file->file_pointer);
if( handle_ferror(file, __func__, "fputc() error [5]") )
{
goto done;
@@ -3044,8 +3101,7 @@ line_sequential_file_read( cblc_file_t *file)
{
file->errnum = 0;
file->io_status = FsErrno;
- size_t characters_read = 0;
- size_t remaining;
+ size_t bytes_read = 0;
bool hit_eof;
// According to IBM:
@@ -3065,8 +3121,11 @@ line_sequential_file_read( cblc_file_t *file)
// characters to the right as undefined. I'm going with IBM,
// it makes more sense to me.
+ charmap_t *charmap = __gg__get_charmap(file->encoding);
+ int stride = charmap->stride();
+
// We first stage the data into the record area.
- int ch;
+ cbl_char_t ch;
long fpos = ftell(file->file_pointer);
if( handle_ferror(file, __func__, "ftell() error") )
@@ -3076,15 +3135,16 @@ line_sequential_file_read( cblc_file_t *file)
}
hit_eof = false;
- while( characters_read < file->record_area_max )
+ while( bytes_read < file->record_area_max )
{
- ch = fgetc(file->file_pointer);
+ ch = 0;
+ fread(&ch, 1, stride, file->file_pointer);
file->errnum = ferror(file->file_pointer);
if( ch == file->delimiter )
{
break;
}
- if( ch == EOF )
+ if( feof(file->file_pointer) )
{
hit_eof = true;
clearerr(file->file_pointer);
@@ -3095,19 +3155,15 @@ line_sequential_file_read( cblc_file_t *file)
fpos = -1;
goto done;
}
- file->default_record->data[characters_read] = (char)ch;
- characters_read += 1;
- }
- remaining = characters_read;
- while(remaining < file->record_area_max )
- {
- // Space fill shorty records
- charmap_t *charmap = __gg__get_charmap(file->encoding);
- file->default_record->data[remaining++] =
-
charmap->mapped_character(ascii_space);
+ memcpy(file->default_record->data+bytes_read, &ch, stride);
+ bytes_read += stride;
}
+ // Space fill shorty records
+ charmap->memset(file->default_record->data+bytes_read,
+ charmap->mapped_character(ascii_space),
+ file->record_area_max - bytes_read);
- if( hit_eof && !characters_read)
+ if( hit_eof && !bytes_read)
{
// We got an end-of-file without characters
file->io_status = FsEofSeq; // "10"
@@ -3120,7 +3176,7 @@ line_sequential_file_read( cblc_file_t *file)
// does another READ:
file->io_status = FsErrno;
}
- else if (characters_read < file->record_area_max)
+ else if (bytes_read < file->record_area_max )
{
// Just discard an early record delimiter
file->io_status = FsRecordLength; // "04"
@@ -3133,18 +3189,6 @@ line_sequential_file_read( cblc_file_t *file)
// Manual: "If the first unread character is the record delimiter, it
// is discarded. Otherwise, the first unread character becomes the
first
// character read by the next READ statement."
- ch = fgetc(file->file_pointer);
- file->errnum = ferror();
- // If that next character isn't a delimiter, put it back:
- if( ch != file->delimiter && ch != EOF)
- {
- ungetc(ch, file->file_pointer);
- }
- else if( handle_ferror(file->file_pointer, __func__, "fgetc() error")
)
- {
- fpos = -1;
- goto done;
- }
#else
// In this code, extra characters before the newline
// are read next time are discarded. GnuCOBOL works this way, and
@@ -3153,11 +3197,12 @@ line_sequential_file_read( cblc_file_t *file)
// SEQUENTIAL; it describes only SEQUENTIAL.
for(;;)
{
- ch = fgetc(file->file_pointer);
+ ch = 0;
+ fread(&ch, 1, stride, file->file_pointer);
file->errnum = ferror(file->file_pointer);
// We can't use handle_ferror() directly, because an EOF is
// a legitimate way to end the last line.
- if( ch == file->delimiter || ch == EOF)
+ if( ch == file->delimiter || feof(file->file_pointer) )
{
clearerr(file->file_pointer);
break;
@@ -3176,7 +3221,7 @@ line_sequential_file_read( cblc_file_t *file)
if( file->record_length )
{
__gg__int128_to_field(file->record_length,
- characters_read,
+ bytes_read/stride,
0,
truncation_e,
NULL);
@@ -3266,14 +3311,27 @@ sequential_file_read( cblc_file_t *file)
if( characters_read < bytes_in_record )
{
charmap_t *charmap = __gg__get_charmap(file->encoding);
- memset( file->default_record->data,
- charmap->mapped_character(ascii_space),
- bytes_to_read);
+ charmap->memset(file->default_record->data,
+ charmap->mapped_character(ascii_space),
+ bytes_to_read);
file->io_status = FsEofSeq; // "10"
fpos = -1;
goto done;
}
+ if( characters_read < file->default_record->capacity )
+ {
+ // The record area is longer than the characters we read. Space-fill
out
+ // to the end:
+
+ charmap_t *charmap = __gg__get_charmap(file->encoding);
+ charmap->memset( file->default_record->data + characters_read,
+ charmap->mapped_character(ascii_space),
+ file->default_record->capacity - characters_read );
+ }
+
+
+
// Let the caller know if we got too few or too many characters
if( bytes_in_record < file->record_area_min
|| bytes_in_record > file->record_area_max )
@@ -3292,7 +3350,7 @@ sequential_file_read( cblc_file_t *file)
if( file->record_length )
{
__gg__int128_to_field(file->record_length,
- characters_read,
+ characters_read/file->stride,
0,
truncation_e,
NULL);
@@ -3570,7 +3628,8 @@ relative_file_read( cblc_file_t *file,
file->prior_read_location = -1;
goto done;
}
- char record_marker;
+ cbl_char_t record_marker;
+ record_marker = 0;
if( pread(rfp.fd, &record_marker, 1, rfp.flag_position) <= 0)
{
goto done;
@@ -4189,9 +4248,7 @@ __gg__file_reopen(cblc_file_t *file, int mode_char)
// Stash the mode_char for later analysis during READ and WRITE
operations
file->mode_char = mode_char;
- char *trimmed_name;
- trimmed_name = get_filename(file);
- if( !trimmed_name[0] )
+ if( !file->filename[0] )
{
bool all_spaces = true;
for(size_t i=0; i<strlen(file->filename); i++)
@@ -4220,7 +4277,7 @@ __gg__file_reopen(cblc_file_t *file, int mode_char)
// achMode is the mode string that gets passed down below to fopen().
random_access_mode = ( file->access == file_access_rnd_e
|| file->access == file_access_dyn_e);
- the_file_exists = access(trimmed_name, F_OK) == 0;
+ the_file_exists = access(file->filename, F_OK) == 0;
file->flags |= the_file_exists ? file_flag_existed_e : file_flag_none_e
;
// We have four operations: INPUT (r) OUTPUT (w) I-O (+) and EXTEND (a)
@@ -4362,7 +4419,7 @@ __gg__file_reopen(cblc_file_t *file, int mode_char)
}
}
- file->file_pointer = fopen(trimmed_name, achMode);
+ file->file_pointer = fopen(file->filename, achMode);
if( file->file_pointer == NULL )
{
file->errnum = errno;
@@ -4406,21 +4463,27 @@ __gg__file_reopen(cblc_file_t *file, int
mode_char)
static void
__io__file_open(cblc_file_t *file,
- char *filename,
- int mode_char,
- int is_quoted)
+ const char *filename,
+ int mode_char)
{
- // 'filename' is a pointer to a malloc() buffer.
- // The 'filename' has to be in the system encoding, typically ASCII
-
- // The complication: A filename can be literal text, it can be from a
COBOL
- // alphanumeric variable, or it can be the name of an environment
variable
- // that contains the actual name of the file. The consequence is that
if
- // you want to call __gg__file_open from anywhere except the
parser_file_open
- // routine, then you had best really know what you are doing.
-
file->errnum = 0;
file->io_status = FsErrno;
+
+ if( filename )
+ {
+ free(file->filename);
+ file->filename = strdup(filename);
+ trim_in_place(file->filename);
+ }
+
+ if( !strlen(file->filename) )
+ {
+ warnx("Warning: %s specified with a filename that is empty",
+ file->name);
+ file->io_status = FsNameError; // "31"
+ goto done;
+ }
+
if( file->file_pointer )
{
// The file is already open:
@@ -4428,16 +4491,9 @@ __io__file_open(cblc_file_t *file,
}
else
{
- // filename is the result of a strdup or malloc. Because both FILE
OPEN
- // and FILE DELETE can establish or change a name, we free it here
and
- // replace it. The same is true in FILE DELETE Format 2
- free(file->filename);
- file->filename = filename;
- file->flags &= ~file_name_quoted_e;
- file->flags |= is_quoted ? file_name_quoted_e : file_flag_none_e;
-
__gg__file_reopen(file, mode_char);
}
+ done:
file->prior_op = file_op_open;
establish_status(file, -1);
}
@@ -4491,10 +4547,6 @@ __io__file_close( cblc_file_t *file, int how )
file_indexed_close(file);
}
- // The filename was malloced. So, we get rid of it here.
- free(file->filename);
- file->filename = NULL;
-
done:
file->prior_op = file_op_close;
establish_status(file, fpos);
@@ -4548,9 +4600,8 @@ public:
static const char constexpr marquee[64] = "libgcobol: gfileio.cc";
typedef void (open_t)( cblc_file_t *file,
- char *filename,
- int mode_char,
- int is_quoted );
+ const char *filename,
+ int mode_char);
typedef void (close_t)( cblc_file_t *file,
int how );
typedef void (start_t)( cblc_file_t *file,
@@ -4565,14 +4616,12 @@ public:
int after,
int lines,
int is_random );
- typedef void (rewrite_t)( cblc_file_t *file,
- size_t length, bool is_random );
- typedef void (delete_t)( cblc_file_t *file,
+ typedef void (rewrite_t)(cblc_file_t *file,
+ size_t length, bool is_random );
+ typedef void (delete_t)(cblc_file_t *file,
bool is_random );
- typedef void (remove_t)( cblc_file_t *file,
- char *filename,
- int is_quoted);
-
+ typedef void (remove_t)(cblc_file_t *file,
+ const char *filename);
open_t *Open;
close_t *Close;
start_t *Start;
@@ -4651,9 +4700,9 @@ gcobol_fileops() {
* Then, in libgcobol, replace direct calls with calls through fileops.
* That is, instead of
*
- * __gg__file_open("foo", "r", false );
+ * __gg__file_open("foo", "r" );
* use
- * gfile->Open("foo", "r", false );
+ * gfile->Open("foo", "r" );
*
* You'll probably want some kind of trampoline to avoid the need to
* generate the Gimple to call through a pointer to a structure:
@@ -4680,13 +4729,13 @@ gcobol_io_funcs() {
extern "C"
void
__gg__file_open(cblc_file_t *file,
+ const cblc_field_t *field_of_name,
char *filename,
- int mode_char,
- int is_quoted)
+ int mode_char)
{
- // The 'filename' has to be in the system encoding, typically ASCII
+ establish_filename(file, field_of_name, filename);
gcobol_io_t *functions = gcobol_io_funcs();
- functions->Open(file, filename, mode_char, is_quoted);
+ functions->Open(file, NULL, mode_char);
}
extern "C"
@@ -4749,11 +4798,14 @@ __gg__file_delete(cblc_file_t *file, bool
is_random)
extern "C"
void
-__gg__file_remove(cblc_file_t *file, char *name, int is_quoted)
+__gg__file_remove( cblc_file_t *file,
+ const cblc_field_t *field_of_name,
+ char *filename)
{
// DELETE FILE Format 2 - removes a file.
+ establish_filename(file, field_of_name, filename);
gcobol_io_t *functions = gcobol_io_funcs();
- functions->Remove(file, name, is_quoted);
+ functions->Remove(file, NULL);
}
/* end interface functions */
diff --git a/libgcobol/gfileio.h b/libgcobol/gfileio.h
index d525500dffe..36df81bb2ea 100644
--- a/libgcobol/gfileio.h
+++ b/libgcobol/gfileio.h
@@ -59,9 +59,9 @@ extern "C"
void __gg__handle_error(const char *function, const char *msg);
void __gg__file_open( cblc_file_t *file,
+ const cblc_field_t *fname,
char *filename,
- int mode_char,
- int is_quoted);
+ int mode_char);
void __gg__file_reopen(cblc_file_t *file, int mode_char);
diff --git a/libgcobol/gmath.cc b/libgcobol/gmath.cc
index 8a9880ba213..be98f7eb522 100644
--- a/libgcobol/gmath.cc
+++ b/libgcobol/gmath.cc
@@ -1097,7 +1097,7 @@ __gg__subtractf1_float_phase2(cbl_arith_format_t ,
const size_t *C_s = __gg__treeplet_3s;
bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
- // This is the assignment phase of an ADD Format 2
+ // This is the assignment phase of an SUBTRACT Format 2
// We take phase1_result and subtract it from C
GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0], C_o[0],
C_s[0]);
@@ -1135,11 +1135,10 @@ __gg__subtractf2_float_phase1(cbl_arith_format_t ,
compute_error
);
- // Subtract that from the B value:
+ // Subtract that subtotal from the B value:
GCOB_FP128 value_b = __gg__float128_from_qualified_field(B[0], B_o[0],
B_s[0]);
- // The two numbers have the same number of rdigits. It's now safe to
add
- // them.
+
phase1_result_float = subtraction_helper_float(value_b,
phase1_result_float, compute_error);
}
@@ -1366,7 +1365,7 @@ __gg__multiplyf1_phase2(cbl_arith_format_t ,
{
if( C[0]->type == FldFloat )
{
- // gixed * float
+ // fixed * float
a_value = (GCOB_FP128) multiply_intermediate_int128;
if( multiply_intermediate_rdigits )
{
diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc
index bf9396ea0bb..af8f3ac42c0 100644
--- a/libgcobol/intrinsic.cc
+++ b/libgcobol/intrinsic.cc
@@ -38,6 +38,7 @@
#include <langinfo.h>
#include <cctype>
+#include <cwctype>
#include <cmath>
#include <cstring>
#include <ctime>
@@ -100,11 +101,17 @@ trim_trailing_spaces(PCHAR left, PCHAR &right, int
mapped_space)
static bool
is_zulu_format(PCHAR left, PCHAR &right, charmap_t *charmap)
{
- int char_Z = charmap->mapped_character(ascii_Z);
+ cbl_char_t char_Z = charmap->mapped_character(ascii_Z);
+ cbl_char_t char_z = charmap->mapped_character(ascii_z);
+ int stride = charmap->stride();
bool retval = false;
- if( right > left )
+ if( right - left >= stride)
{
- retval = std::toupper((unsigned char)*(right-1)) == char_Z;
+ cbl_char_t last_character = charmap->getch(right-stride, size_t(0));
+ if( last_character == char_Z || last_character == char_z )
+ {
+ retval = true;
+ }
}
return retval;
}
@@ -228,11 +235,11 @@ static
void
string_to_dest(cblc_field_t *dest, const char *psz)
{
+ charmap_t *charmap = __gg__get_charmap(dest->encoding);
size_t dest_length = dest->capacity;
- size_t source_length = strlen(psz);
+ size_t source_length = charmap->strlen(psz);
size_t length = std::min(dest_length, source_length);
- charmap_t *charmap = __gg__get_charmap(dest->encoding);
- memset(dest->data, charmap->mapped_character(ascii_space),
dest_length);
+ charmap->memset(dest->data, charmap->mapped_character(ascii_space),
dest_length);
memcpy(dest->data, psz, length);
}
@@ -574,6 +581,7 @@ get_all_time( const cblc_field_t *dest, // needed for
the target encoding
ctm.day_of_week+1,
ctm.day_of_year,
ctm.ZZZZ);
+
__gg__convert_encoding(PTRCAST(char, stime),
DEFAULT_SOURCE_ENCODING,
dest->encoding);
@@ -801,7 +809,7 @@ ftime_replace(char *dest,
char const * const dest_end,
char const * source,
char const * const source_end,
- charmap_t * charmap_source,
+ charmap_t * charmap,
char const * const ftime)
{
// This routine is highly dependent on the source format being correct.
@@ -824,33 +832,38 @@ ftime_replace(char *dest,
static const int OFFSET_TO_DOY = 34;
static const int OFFSET_TO_ZZZZ = 37;
- unsigned int decimal_point =
-
charmap_source->mapped_character(__gg__get_decimal_point());
- unsigned int source_Y = charmap_source->mapped_character(ascii_Y
);
- unsigned int source_W = charmap_source->mapped_character(ascii_W
);
- unsigned int source_s = charmap_source->mapped_character(ascii_s
);
- unsigned int source_m = charmap_source->mapped_character(ascii_m
);
- unsigned int source_h = charmap_source->mapped_character(ascii_h
);
- unsigned int source_plus =
charmap_source->mapped_character(ascii_plus);
- unsigned int source_D = charmap_source->mapped_character(ascii_D
);
- unsigned int source_M = charmap_source->mapped_character(ascii_M
);
+ int stride = charmap->stride();
+
+ cbl_char_t decimal_point =
+ charmap->mapped_character(__gg__get_decimal_point());
+ cbl_char_t source_Y = charmap->mapped_character(ascii_Y );
+ cbl_char_t source_W = charmap->mapped_character(ascii_W );
+ cbl_char_t source_s = charmap->mapped_character(ascii_s );
+ cbl_char_t source_m = charmap->mapped_character(ascii_m );
+ cbl_char_t source_h = charmap->mapped_character(ascii_h );
+ cbl_char_t source_plus = charmap->mapped_character(ascii_plus);
+ cbl_char_t source_D = charmap->mapped_character(ascii_D );
+ cbl_char_t source_M = charmap->mapped_character(ascii_M );
while( source < source_end && dest < dest_end )
{
- unsigned char fchar = *source;
+ cbl_char_t fchar = charmap->getch(source, size_t(0));
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
// need to use ZZZZ rather than YYYY:
- src = ftime + OFFSET_TO_YYYY;
+ src = ftime + OFFSET_TO_YYYY*stride;
const char *p = source;
+ size_t index = 0;
while(p < source_end)
{
- if( (unsigned char)*p++ == source_W )
+ //if( (unsigned char)*p++ == source_W )
+ if( charmap->getch(source, &index) == source_W )
{
- src = ftime + OFFSET_TO_ZZZZ;
+ src = ftime + OFFSET_TO_ZZZZ*stride;
}
+ p += stride;
}
ncount = 4;
@@ -859,43 +872,43 @@ ftime_replace(char *dest,
{
// This can only be a MM
ncount = 2;
- src = ftime + OFFSET_TO_MM;
+ src = ftime + OFFSET_TO_MM*stride;
}
else if( fchar == source_D )
{
// It can be a D, DD or DDD
- if( (unsigned char)source[2] == source_D )
+ if( charmap->getch(source, 2*stride) == source_D )
{
ncount = 3;
- src = ftime + OFFSET_TO_DOY;
+ src = ftime + OFFSET_TO_DOY*stride;
}
- else if( (unsigned char)source[1] == source_D )
+ else if( charmap->getch(source, 1*stride) == source_D )
{
ncount = 2;
- src = ftime + OFFSET_TO_DD;
+ src = ftime + OFFSET_TO_DD*stride;
}
else
{
ncount = 1;
- src = ftime + OFFSET_TO_DOW;
+ src = ftime + OFFSET_TO_DOW*stride;
}
}
else if( fchar == source_plus )
{
saw_plus_sign = true;
ncount = 1;
- src = ftime + OFFSET_TO_OFFSET;
+ src = ftime + OFFSET_TO_OFFSET*stride;
}
else if( fchar == source_h )
{
ncount = 2;
if(saw_plus_sign)
{
- src = ftime + OFFSET_TO_OFFSET_HOUR;
+ src = ftime + OFFSET_TO_OFFSET_HOUR*stride;
}
else
{
- src = ftime + OFFSET_TO_HOUR;
+ src = ftime + OFFSET_TO_HOUR*stride;
}
}
else if( fchar == source_m )
@@ -903,11 +916,11 @@ ftime_replace(char *dest,
ncount = 2;
if(saw_plus_sign)
{
- src = ftime + OFFSET_TO_OFFSET_MINUTE;
+ src = ftime + OFFSET_TO_OFFSET_MINUTE*stride;
}
else
{
- src = ftime + OFFSET_TO_MINUTE;
+ src = ftime + OFFSET_TO_MINUTE*stride;
}
}
else if( fchar == decimal_point )
@@ -922,18 +935,18 @@ ftime_replace(char *dest,
{
// There can be a variable number of fractional 's'
ncount = -1;
- src = ftime + OFFSET_TO_FRACTION;
+ src = ftime + OFFSET_TO_FRACTION*stride;
}
else
{
ncount = 2;
- src = ftime + OFFSET_TO_SECOND;
+ src = ftime + OFFSET_TO_SECOND*stride;
}
}
else if( fchar == source_W )
{
ncount = 3;
- src = ftime + OFFSET_TO_WEEK;
+ src = ftime + OFFSET_TO_WEEK*stride;
}
else
{
@@ -946,18 +959,22 @@ ftime_replace(char *dest,
{
// This indicates special processing for a variable number of 's'
// characters
- while((unsigned char)*source == source_s && dest < dest_end)
+ while(charmap->getch(source, size_t(0)) == source_s && dest <
dest_end)
{
- source += 1;
- *dest++ = *src++;
+ source += stride;
+ memcpy(dest, src, stride);
+ dest += stride;
+ src += stride;
}
}
else
{
- source += ncount;
+ source += ncount*stride;
while(ncount-- && dest < dest_end)
{
- *dest++ = *src++;
+ memcpy(dest, src, stride);
+ dest += stride;
+ src += stride;
}
}
}
@@ -1177,26 +1194,31 @@ __gg__char( cblc_field_t *dest,
}
// We need to convert the ch character to the destination encoding.
- const char achFrom[2] = {static_cast<char>(ch), '\0'};
+ // THIS IS A KLUDGE UNTIL WE MAKE THE CURRENT_COLLATION TO BE A MAP OF
+ // WIDE CHARACTERS!
+ charmap_t *charmap_dest = __gg__get_charmap(dest->encoding);
+
+ cbl_char_t achFrom = 0;
+ memcpy(&achFrom, &ch, 1);
size_t charsout;
const char *converted = __gg__iconverter(__gg__display_encoding,
dest->encoding,
- achFrom,
+ &achFrom,
1,
&charsout );
// Pick up our character, because mapped_character() might clobber
// the converted contents.
- int converted_char = *converted; // cppcheck-suppress variableScope
+ int converted_char = 0;
+ memcpy(&converted_char, converted, charmap_dest->stride());
// Space fill the dest:
- charmap_t *charmap_dest = __gg__get_charmap(dest->encoding);
- memset(dest->data,
- charmap_dest->mapped_character(ascii_space),
- dest->capacity);
+ charmap_dest-> memset(dest->data,
+ charmap_dest->mapped_character(ascii_space),
+ dest->capacity);
// Make the first character of the destination equal to our converted
// character:
if( ch > -1 && charsout == 1 )
{
- dest->data[0] = converted_char;
+ charmap_dest->putch(converted_char, dest->data, size_t(0));
}
}
@@ -1278,10 +1300,16 @@ __gg__current_date(cblc_field_t *dest)
char retval[DATE_STRING_BUFFER_SIZE];
timespec_to_string(retval, tp);
- __gg__convert_encoding(PTRCAST(char, retval),
- DEFAULT_SOURCE_ENCODING,
- dest->encoding);
- string_to_dest(dest, retval);
+
+ size_t bytes_converted;
+ char *converted = __gg__miconverter(__gg__console_encoding,
+ dest->encoding,
+ retval,
+ strlen(retval),
+ &bytes_converted);
+ __gg__field_from_string(dest, 0, dest->capacity, converted,
bytes_converted);
+ __gg__adjust_dest_size(dest, bytes_converted);
+ free(converted);
}
extern "C"
@@ -1524,29 +1552,30 @@ __gg__formatted_current_date( cblc_field_t *dest,
// Destination string
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);
+ cbl_char_t dest_space = charmap_to->mapped_character(ascii_space);
+ cbl_char_t format_Z = charmap_from->mapped_character(ascii_Z);
+ cbl_char_t format_z = charmap_from->mapped_character(ascii_z);
// Establish the destination, and set it to spaces
char *d = PTRCAST(char, dest->data);
const char *dend = d + dest->capacity;
- memset(d, dest_space, dest->capacity);
+ charmap_to->memset(d, dest_space, dest->capacity);
// Establish the formatting string:
const char *format = PTRCAST(char, (input->data+input_offset));
const char *format_end = format + input_size;
bool is_zulu = false;
-
const char *p = format;
while( p < format_end )
{
- int ch = *p++;
- if( ch == format_Z )
+ cbl_char_t ch = charmap_from->getch(p, size_t(0));
+ if( ch == format_Z || ch == format_z)
{
is_zulu = true;
break;
}
+ p += charmap_from->stride();
}
struct cbl_timespec ts = {};
@@ -1574,9 +1603,10 @@ __gg__formatted_current_date( cblc_field_t *dest,
// Destination string
// Convert seconds west of UTC to minutes east of UTC
ctm.tz_offset = -timezone/60;
- char achftime[64];
+ char achftime[256];
get_all_time(dest, achftime, ctm);
ftime_replace(d, dend, format, format_end, charmap_from, achftime);
+ return;
}
extern "C"
@@ -1586,22 +1616,23 @@ __gg__formatted_date(cblc_field_t *dest, //
Destination string
size_t arg1_offset,
size_t arg1_size,
const cblc_field_t *arg2, // integer date
- size_t arg2_offset,
+ 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);
+ cbl_encoding_t from = arg1->encoding;
+
charmap_t *charmap_to = __gg__get_charmap(to);
+ charmap_t *charmap_from = __gg__get_charmap(from);
- int dest_space = charmap_to->mapped_character(ascii_space);
+ cbl_char_t dest_space = charmap_to->mapped_character(ascii_space);
// Establish the destination, and set it to spaces
char *d = PTRCAST(char, dest->data);
const char *dend = d + dest->capacity;
- memset(d, dest_space, dest->capacity);
+ charmap_to->memset(d, dest_space, dest->capacity);
// Establish the formatting string:
char *format = PTRCAST(char, (arg1->data+arg1_offset));
@@ -1611,11 +1642,11 @@ __gg__formatted_date(cblc_field_t *dest, //
Destination string
populate_ctm_from_date(ctm, arg2, arg2_offset, arg2_size);
- char achftime[64];
+ char achftime[256];
get_all_time(dest, achftime, ctm);
if( __gg__exception_code )
{
- memset(d, dest_space, dend-d);
+ charmap_to->memset(d, dest_space, dend-d);
}
else
{
@@ -1671,7 +1702,7 @@ __gg__formatted_datetime( cblc_field_t *dest, //
Destination string
convert_to_zulu(ctm);
}
- char achftime[64];
+ char achftime[256];
get_all_time(dest, achftime, ctm);
if( __gg__exception_code )
{
@@ -1710,7 +1741,7 @@ __gg__formatted_time( cblc_field_t *dest,//
Destination string
// Establish the destination, and set it to spaces
char *d = PTRCAST(char, dest->data);
const char *dend = d + dest->capacity;
- memset(d, dest_space, dest->capacity);
+ charmap_to->memset(d, dest_space, dest->capacity);
// Establish the formatting string:
char *format = PTRCAST(char, (par1->data+par1_o));
@@ -1734,11 +1765,11 @@ __gg__formatted_time( cblc_field_t *dest,//
Destination string
convert_to_zulu(ctm);
}
- char achftime[64];
+ char achftime[256];
get_all_time(dest, achftime, ctm);
if( __gg__exception_code )
{
- memset(d, dest_space, dend-d);
+ charmap_to->memset(d, dest_space, dend-d);
}
else
{
@@ -2066,6 +2097,54 @@ __gg__max(cblc_field_t *dest,
}
}
+static void
+change_case( cblc_field_t *dest,
+ const cblc_field_t *input,
+ size_t input_offset,
+ size_t input_size,
+ std::wint_t (changer)( std::wint_t ch )
+ )
+ {
+ cbl_encoding_t enc_to = dest->encoding;
+ cbl_encoding_t enc_from = input->encoding;
+ cbl_encoding_t enc_work = DEFAULT_32_ENCODING;
+
+ // In order to handle any input encoding, we convert to UTF32:
+ size_t converted_bytes;
+ const char *converted = __gg__iconverter(enc_from,
+ enc_work,
+ input->data+input_offset,
+ input_size,
+ &converted_bytes);
+ // Make a copy of it to prevent the static nature of iconverter from
causing
+ // trouble:
+ cbl_char_t *duped =
+ static_cast<cbl_char_t *>(__gg__memdup(converted,
converted_bytes));
+ cbl_char_t *pend = duped + converted_bytes / width_of_utf32;
+
+ // Use the designated case changer:
+ std::transform(duped, pend, duped,
+ [&changer](cbl_char_t c) { return changer(c); });
+
+ // Convert that modified string to the destination encoding:
+ converted = __gg__iconverter(enc_work,
+ enc_to,
+ duped,
+ converted_bytes,
+ &converted_bytes);
+ free(duped);
+
+ char *duped2 = static_cast<char *>(__gg__memdup(converted,
converted_bytes));
+ __gg__field_from_string(dest,
+ 0,
+ dest->capacity,
+ duped2,
+ converted_bytes);
+ free(duped2);
+ __gg__adjust_dest_size(dest, converted_bytes);
+ }
+
+
extern "C"
void
__gg__lower_case( cblc_field_t *dest,
@@ -2073,27 +2152,17 @@ __gg__lower_case( cblc_field_t *dest,
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);
+ return change_case(dest, input, input_offset, input_size,
std::towlower);
+ }
- size_t dest_length = dest->capacity;
- size_t source_length = input_size;
- 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_SOURCE_ENCODING);
- std::transform(dest->data, dest->data + dest_length, dest->data,
- [](unsigned char c) { return std::tolower(c); });
- __gg__convert_encoding_length(PTRCAST(char, dest->data),
- length,
- DEFAULT_SOURCE_ENCODING,
- to);
+extern "C"
+void
+__gg__upper_case( cblc_field_t *dest,
+ const cblc_field_t *input,
+ size_t input_offset,
+ size_t input_size)
+ {
+ return change_case(dest, input, input_offset, input_size,
std::towupper);
}
extern "C"
@@ -2401,7 +2470,7 @@ numval( cblc_field_t *dest,
PTRCAST(char, input->data +
input_offset),
input_size,
&nbytes);
- const char *pend = p + input_size;
+ const char *pend = p + nbytes;
int errpos = 0;
__int128 retval = 0;
@@ -2702,7 +2771,7 @@ numval_c( cblc_field_t *dest,
&nbytes);
char *pstart = strdup(converted);
massert(pstart);
- char *pend = pstart + src_size;
+ char *pend = pstart + nbytes;
char *p = pstart;
GCOB_FP128 retval = 0;
@@ -3447,7 +3516,8 @@ __gg__trim( cblc_field_t *dest,
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 stride = charmap->stride();
+ cbl_char_t mapped_space = charmap->mapped_character(ascii_space);
int rdigits;
__int128 type = __gg__binary_value_from_qualified_field(&rdigits,
@@ -3466,6 +3536,8 @@ __gg__trim( cblc_field_t *dest,
"be an intermediate alphanumeric\n");
abort();
}
+
+ // What is this all about?
dest->capacity = dest->offset;
// Make a copy of the input:
@@ -3476,27 +3548,29 @@ __gg__trim( cblc_field_t *dest,
// 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 = copy;
- char *right = left + arg1_size-1;
+ char *right = left + arg1_size-stride;
// Find left and right: the first and last non-spaces
while( left <= right )
{
- if( *left != mapped_space && *right != mapped_space )
+ cbl_char_t cleft = charmap->getch(left, (size_t)0);
+ cbl_char_t cright = charmap->getch(right, (size_t)0);
+
+ if( cleft != mapped_space && cright != mapped_space )
{
break;
}
- if( *left == mapped_space )
+ if( cleft == mapped_space )
{
- left += 1;
+ left += stride;
}
- if( *right == mapped_space )
+ if( cright == mapped_space )
{
- right -= 1;
+ right -= stride;
}
}
if( type == LEADING )
@@ -3517,24 +3591,13 @@ __gg__trim( cblc_field_t *dest,
// When the arg1 input string was empty, we want left to be right+1.
// The left/right loop can sometimes end up with left equal to
right+2.
// That needs to be fixed:
- left = right+1;
+ left = right+stride;
}
- size_t ncount = right+1 - left;
+ size_t ncount = right+stride - left;
__gg__adjust_dest_size(dest, ncount);
- char *dest_left = PTRCAST(char, dest->data);
- char *dest_right = dest_left + dest->capacity - 1;
- const char *dest_end = dest_left + dest->capacity;
-
- while( dest_left <= dest_right && left <= right )
- {
- *dest_left++ = *left++;
- }
- while(dest_left < dest_end)
- {
- *dest_left++ = mapped_space;
- }
+ memmove(dest->data, left, ncount);
}
#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R
@@ -3632,34 +3695,29 @@ __gg__reverse(cblc_field_t *dest,
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);
+ charmap_t *charmap = __gg__get_charmap(to);
+ size_t stride = charmap->stride();
- // Make a copy of the input
- char *copy = static_cast<char *>(malloc(length));
- massert(copy);
- memcpy(copy, input->data+input_offset, length);
+ size_t dest_length = dest->capacity;
// 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] = copy[source_length-1-i];
- }
- if( (dest->attr & intermediate_e) )
- {
- dest->capacity = std::min(dest_length, source_length);
- }
-
- free(copy);
+ size_t bytes_converted;
+ const char *converted = __gg__iconverter(from,
+ to,
+ input->data+input_offset,
+ input_size,
+ &bytes_converted);
+ // copy over characters from the end of the copy to the beginning of
dest:
+ size_t i_from = bytes_converted - stride;
+ size_t i_to = 0;
+ while( i_from < bytes_converted && i_to < dest_length )
+ {
+ cbl_char_t ch = charmap->getch(converted, i_from);
+ charmap->putch(ch, dest->data+dest->offset, i_to);
+ i_from -= stride;
+ i_to += stride;
+ }
+ __gg__adjust_dest_size(dest, i_to);
}
extern "C"
@@ -3892,36 +3950,6 @@ __gg__test_day_yyyyddd( cblc_field_t *dest,
NULL);
}
-extern "C"
-void
-__gg__upper_case( cblc_field_t *dest,
- 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;
- 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_SOURCE_ENCODING);
- std::transform(dest->data, dest->data + dest_length, dest->data,
- [](unsigned char c) { return std::toupper(c); });
- __gg__convert_encoding_length(PTRCAST(char, dest->data),
- length,
- DEFAULT_SOURCE_ENCODING,
- to);
- }
-
extern "C"
void
__gg__variance( cblc_field_t *dest,
@@ -4552,43 +4580,32 @@ fill_cobol_tm(cobol_tm &ctm,
size_t par2_offset,
size_t par2_size)
{
- // Establish the formatting string:
- char *format = PTRCAST(char, (par1->data+par1_offset));
- char *format_end = format + par1_size;
-
- // Establish the string to be checked:
- 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 source_plus = charmap_checked->mapped_character(ascii_plus);
- int source_minus = charmap_checked->mapped_character(ascii_minus);
- int source_zero = charmap_checked->mapped_character(ascii_zero);
-
- 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 );
- char decimal_point
- =
charmap_format->mapped_character(__gg__get_decimal_point());
+ // It turns out to be just easier to convert the strings to ASCII space
to
+ // do the conversion of par2 against the format in par1:
+ charmap_t *charmap = __gg__get_charmap(DEFAULT_SOURCE_ENCODING);
+
+ size_t bytes_converted;
+ char *par1_c = __gg__miconverter(par1->encoding,
+ DEFAULT_SOURCE_ENCODING,
+ par1->data+par1_offset,
+ par1_size,
+ &bytes_converted);
+ char *format = par1_c;
+ char *format_end = format + bytes_converted;
+
+ char *par2_c = __gg__miconverter(par2->encoding,
+ DEFAULT_SOURCE_ENCODING,
+ par2->data+par2_offset,
+ par2_size,
+ &bytes_converted);
+ char *source = par2_c;
+ char *source_end = source + bytes_converted;
+
+ char decimal_point = __gg__get_decimal_point();
// Let's eliminate trailing spaces...
- trim_trailing_spaces(format, format_end, format_space);
- trim_trailing_spaces(source, source_end, checked_space);
+ trim_trailing_spaces(format, format_end, ascii_space);
+ trim_trailing_spaces(source, source_end, ascii_space);
bool in_offset = false;
bool in_nanoseconds = false;
@@ -4605,10 +4622,10 @@ fill_cobol_tm(cobol_tm &ctm,
{
unsigned char ch = *format;
- if( ch == format_T
- || ch == format_colon
- || ch == format_minus
- || ch == format_W)
+ if( ch == ascii_T
+ || ch == ascii_colon
+ || ch == ascii_minus
+ || ch == ascii_W)
{
// These are just formatting characters. They need to be
duplicated,
// but are otherwise ignored.
@@ -4620,34 +4637,34 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_plus )
+ if( ch == ascii_plus )
{
// This flags a following hhmm offset. It needs to match a '+' or
'-'
- if( (unsigned char)*source != source_plus
- && (unsigned char)*source != source_minus
- && (unsigned char)*source != source_zero)
+ if( (unsigned char)*source != ascii_plus
+ && (unsigned char)*source != ascii_minus
+ && (unsigned char)*source != ascii_zero)
{
break;
}
- if( (unsigned char)*source == format_zero )
+ if( (unsigned char)*source == ascii_zero )
{
// The next four characters have to be zeroes
- if( (unsigned char)source[1] != format_zero )
+ if( (unsigned char)source[1] != ascii_zero )
{
retval += 1;
break;
}
- if( (unsigned char)source[2] != format_zero )
+ if( (unsigned char)source[2] != ascii_zero )
{
retval += 2;
break;
}
- if( (unsigned char)source[3] != format_zero )
+ if( (unsigned char)source[3] != ascii_zero )
{
retval += 3;
break;
}
- if( (unsigned char)source[4] != format_zero )
+ if( (unsigned char)source[4] != ascii_zero )
{
retval += 4;
break;
@@ -4671,9 +4688,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_Y )
+ if( ch == ascii_Y )
{
- errpos = gets_year(source, source_end, charmap_checked, ctm);
+ errpos = gets_year(source, source_end, charmap, ctm);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4683,9 +4700,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_M )
+ if( ch == ascii_M )
{
- errpos = gets_month(source, source_end, charmap_checked, ctm);
+ errpos = gets_month(source, source_end, charmap, ctm);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4695,13 +4712,13 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_D )
+ if( ch == ascii_D )
{
// We have three possibilities: DDD, DD, and D
- if( (unsigned char)format[1] != format_D )
+ if( (unsigned char)format[1] != ascii_D )
{
// A singleton 'D' is a day-of-week
- errpos = gets_day_of_week(source, source_end, charmap_checked,
ctm);
+ errpos = gets_day_of_week(source, source_end, charmap, ctm);
if( errpos > 0)
{
retval += errpos - 1;
@@ -4709,10 +4726,10 @@ fill_cobol_tm(cobol_tm &ctm,
}
bump = 1;
}
- else if( (unsigned char)format[2] != format_D )
+ else if( (unsigned char)format[2] != ascii_D )
{
// This is DD, for day-of-month
- errpos = gets_day(source, source_end, charmap_checked, ctm);
+ errpos = gets_day(source, source_end, charmap, ctm);
if( errpos > 0)
{
retval += errpos - 1;
@@ -4724,7 +4741,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, charmap_checked,
ctm);
+ errpos = gets_day_of_year(source, source_end, charmap, ctm);
if( errpos > 0)
{
retval += errpos - 1;
@@ -4735,9 +4752,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_w )
+ if( ch == ascii_w )
{
- errpos = gets_week(source, source_end, charmap_checked, ctm);
+ errpos = gets_week(source, source_end, charmap, ctm);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4747,9 +4764,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_h )
+ if( ch == ascii_h )
{
- errpos = gets_hours(source, source_end, charmap_checked, ctm,
in_offset);
+ errpos = gets_hours(source, source_end, charmap, ctm, in_offset);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4759,9 +4776,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_m )
+ if( ch == ascii_m )
{
- errpos = gets_minutes(source, source_end, charmap_checked, ctm,
in_offset);
+ errpos = gets_minutes(source, source_end, charmap, ctm, in_offset);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4771,9 +4788,9 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_s && !in_nanoseconds )
+ if( ch == ascii_s && !in_nanoseconds )
{
- errpos = gets_seconds(source, source_end, charmap_checked, ctm);
+ errpos = gets_seconds(source, source_end, charmap, ctm);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4783,7 +4800,7 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_s && in_nanoseconds )
+ if( ch == ascii_s && in_nanoseconds )
{
// Peel off digits to the right of the decimal point one at a time
errpos = gets_nanoseconds(format,
@@ -4791,8 +4808,8 @@ fill_cobol_tm(cobol_tm &ctm,
source,
source_end,
ctm,
- charmap_format,
- charmap_checked);
+ charmap,
+ charmap);
if( errpos > 0 )
{
retval += errpos - 1;
@@ -4802,11 +4819,11 @@ fill_cobol_tm(cobol_tm &ctm,
goto proceed;
}
- if( ch == format_Z || ch == format_z )
+ if( ch == ascii_Z || ch == ascii_z )
{
// This has to be the end of the road
- if( (unsigned char)source[0] != format_Z
- && (unsigned char)source[0] != format_z )
+ if( (unsigned char)source[0] != ascii_Z
+ && (unsigned char)source[0] != ascii_z )
{
retval += 0;
break;
@@ -4829,9 +4846,10 @@ proceed:
{
// This means we processed the entire format string without seeing an
error
retval = 0;
-
// Otherwise, either the format or source was too short
}
+ free(par1_c);
+ free(par2_c);
return retval;
}
@@ -4914,7 +4932,8 @@ __gg__seconds_from_formatted_time(cblc_field_t
*dest,
}
else
{
- retval = (double)(ctm.hh * 3600 + ctm.mm * 60 + ctm.ss) +
ctm.nanoseconds/1000000000.;
+ retval = (double)(ctm.hh * 3600 + ctm.mm * 60 + ctm.ss)
+ + ctm.nanoseconds/1000000000.;
}
__gg__double_to_target( dest,
retval,
@@ -4928,16 +4947,34 @@ __gg__hex_of(cblc_field_t *dest,
size_t field_offset,
size_t field_size)
{
- charmap_t *charmap = __gg__get_charmap(dest->encoding);
+ // We are going to build the hex string up here, in ascii, and convert
to the
+ // the destination encoding at the end.
+
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++)
+
+ // Dest size is two hex characters per input byte.
+ size_t build_size = 2 * field_size;
+
+ // Build up the hex string in ascii:
+ char *build = static_cast<char *>(malloc(build_size));
+ massert(build);
+ for(size_t i=0; i<field_size; i++)
{
unsigned char byte = (field->data+field_offset)[i];
- dest->data[2*i ] = charmap->mapped_character(hex[byte>>4]);
- dest->data[2*i+1] = charmap->mapped_character(hex[byte&0xF]);
+ build[2*i ] = hex[byte>>4];
+ build[2*i+1] = hex[byte&0xF];
}
+ // Convert the hex string to the destination encoding:
+ size_t converted_bytes;
+ const char *converted = __gg__iconverter(DEFAULT_SOURCE_ENCODING,
+ dest->encoding,
+ build,
+ build_size,
+ &converted_bytes);
+ // And put it into place:
+ __gg__adjust_dest_size(dest, converted_bytes);
+ memcpy(dest->data, converted, converted_bytes);
+ free(build);
}
extern "C"
@@ -5249,11 +5286,11 @@ __gg__numval_f( cblc_field_t *dest,
&nbytes);
GCOB_FP128 value = 0;
const char *data = converted;
- const char *data_end = data + source_size;
+ const char *data_end = data + nbytes;
int error = floating_format_tester( data,
data_end);
- if( error || source_size >= 256 )
+ if( error || nbytes >= 256 )
{
exception_raise(ec_argument_function_e);
}
@@ -5296,7 +5333,7 @@ __gg__test_numval_f(cblc_field_t *dest,
&nbytes);
const char *data = converted;
- const char *data_end = data + source_size;
+ const char *data_end = data + nbytes;
int error = floating_format_tester( data,
data_end);
__gg__int128_to_field(dest,
@@ -5711,11 +5748,15 @@ __gg__locale_date(cblc_field_t *dest,
strcpy(ach, nl_langinfo(D_FMT));
strftime(ach, sizeof(ach), nl_langinfo(D_FMT), &tm);
}
- __gg__convert_encoding(ach,
- DEFAULT_SOURCE_ENCODING,
- dest->encoding);
- memcpy(dest->data, ach, strlen(ach));
- __gg__adjust_dest_size(dest, strlen(ach));
+ size_t bytes_converted;
+ char *converted = __gg__miconverter(__gg__console_encoding,
+ dest->encoding,
+ ach,
+ strlen(ach),
+ &bytes_converted);
+ __gg__field_from_string(dest, 0, dest->capacity, converted,
bytes_converted);
+ __gg__adjust_dest_size(dest, bytes_converted);
+ free(converted);
}
extern "C"
@@ -5749,11 +5790,15 @@ __gg__locale_time(cblc_field_t *dest,
strftime(ach, sizeof(ach), nl_langinfo(T_FMT), &tm);
}
- __gg__convert_encoding(ach,
- DEFAULT_SOURCE_ENCODING,
- dest->encoding);
- memcpy(dest->data, ach, strlen(ach));
- __gg__adjust_dest_size(dest, strlen(ach));
+ size_t bytes_converted;
+ char *converted = __gg__miconverter(__gg__console_encoding,
+ dest->encoding,
+ ach,
+ strlen(ach),
+ &bytes_converted);
+ __gg__field_from_string(dest, 0, dest->capacity, converted,
bytes_converted);
+ __gg__adjust_dest_size(dest, bytes_converted);
+ free(converted);
}
extern "C"
@@ -5788,10 +5833,13 @@ __gg__locale_time_from_seconds( cblc_field_t
*dest,
tm.tm_sec = seconds % 100;
strftime(ach, sizeof(ach), nl_langinfo(T_FMT), &tm);
}
-
- __gg__convert_encoding(ach,
- DEFAULT_SOURCE_ENCODING,
- dest->encoding);
- memcpy(dest->data, ach, strlen(ach));
- __gg__adjust_dest_size(dest, strlen(ach));
+ size_t bytes_converted;
+ char *converted = __gg__miconverter(__gg__console_encoding,
+ dest->encoding,
+ ach,
+ strlen(ach),
+ &bytes_converted);
+ __gg__field_from_string(dest, 0, dest->capacity, converted,
bytes_converted);
+ __gg__adjust_dest_size(dest, bytes_converted);
+ free(converted);
}