Skip to content

Commit

Permalink
Merge SVN 5021
Browse files Browse the repository at this point in the history
  • Loading branch information
ddeclerck committed Oct 2, 2024
1 parent 2575713 commit c6ea0f0
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 84 deletions.
10 changes: 10 additions & 0 deletions libcob/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@
* fileio.c (cob_file_sort_options), common.h: new function to pass more
options, so far only used to set flag_merge

2023-04-13 Simon Sobisch <[email protected]>

* intrinsic.c (test_digit, cob_intr_hex_to_char, cob_intr_locale_date,
cob_intr_locale_time), move.c (cob_move_alphanum_to_display,
cob_get_s64_pic9): prefer range check over isdigit for improved speed
* numeric.c (cob_decimal_get_packed): use COB_D2I instead of subtracting
* intrinsic.c (cob_intr_hex_to_char): minor refactoring for speedup
* intrinsic.c (cob_intr_hex_of): rewritten to use hex value table instead
of sprintf, saving around 80% of cpu instructions

2023-03-03 Simon Sobisch <[email protected]>

* common.c, common.h: new external field + define COB_ZEROES_ALPHABETIC /
Expand Down
11 changes: 11 additions & 0 deletions libcob/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -7118,6 +7118,17 @@ cob_open (cob_file *f, const enum cob_open_mode mode, const int sharing, cob_fie
return;
}

/* Check for _bad_ quotes */
if (file_open_name[0] == '"'
|| file_open_name[0] == '\'') {
const size_t len = strlen (file_open_name) - 1;
if (len == 0
|| file_open_name[len] != file_open_name[0]) {
cob_file_save_status (f, fnstatus, COB_STATUS_31_INCONSISTENT_FILENAME);
return;
}
}

if (file_open_name[0] == 0) {
cob_file_save_status (f, fnstatus, COB_STATUS_31_INCONSISTENT_FILENAME);
return;
Expand Down
82 changes: 47 additions & 35 deletions libcob/intrinsic.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,18 +488,20 @@ setup_cob_log_ten (void)
static void
make_field_entry (cob_field *f)
{
unsigned char *s;
struct calc_struct *calc_temp;
unsigned char *s;

calc_temp = calc_base + curr_entry;
curr_field = &calc_temp->calc_field;
if (f->size > calc_temp->calc_size) {
/* set new temporary field data, storing its size */
if (curr_field->data) {
cob_free (curr_field->data);
}
calc_temp->calc_size = f->size + 1;
s = cob_malloc (f->size + 1U);
} else {
/* reuse last temporary field data */
s = curr_field->data;
memset (s, 0, f->size);
}
Expand Down Expand Up @@ -2622,15 +2624,19 @@ test_char (const char wanted, const char *str, int *offset)
}

static COB_INLINE COB_A_INLINE int
test_digit (const unsigned char ch, int *offset)
test_char_in_range (const char min, const char max, const char ch, int *offset)
{
return test_char_cond (isdigit (ch), offset);
return test_char_cond (min <= ch && ch <= max, offset);
}

static COB_INLINE COB_A_INLINE int
test_char_in_range (const char min, const char max, const char ch, int *offset)
test_digit (const unsigned char ch, int *offset)
{
return test_char_cond (min <= ch && ch <= max, offset);
#if 0 /* note: as isdigit is locale-aware (slower and not what we want), we use the range instead */
return test_char_cond (isdigit (ch), offset);
#else
return test_char_in_range ('0', '9', ch, offset);
#endif
}

static int test_millenium (const char *date, int *offset, int *millenium)
Expand Down Expand Up @@ -3914,19 +3920,24 @@ cob_intr_bit_to_char (cob_field *srcfield)
cob_field *
cob_intr_hex_of (cob_field *srcfield)
{
cob_field field;
const char hex_val[] = "0123456789ABCDEF";

/* FIXME later: srcfield may be of category national - or later bit... */
const size_t size = srcfield->size * 2;
size_t i, j;
cob_field field;

COB_FIELD_INIT (size, NULL, &const_alpha_attr);
make_field_entry (&field);

for (i = j = 0; i < srcfield->size; ++i) {
char buff[3];
sprintf (buff, "%02X", srcfield->data[i]);
curr_field->data[j++] = buff[0];
curr_field->data[j++] = buff[1];
{
register unsigned char *ret_pos = curr_field->data;
register unsigned char *src_pos = srcfield->data;
const unsigned char *src_end = src_pos + srcfield->size;

while (src_pos < src_end) {
*ret_pos++ = hex_val[(*src_pos >> 4) & 0xF];
*ret_pos++ = hex_val[*src_pos++ & 0xF];
}
}
return curr_field;
}
Expand All @@ -3937,7 +3948,7 @@ cob_intr_hex_to_char (cob_field *srcfield)
cob_field field;
const size_t size = srcfield->size / 2;
const unsigned char *end = srcfield->data + size * 2;
unsigned char *hex_char, *p;
register unsigned char *hex_char, *p;

if (size * 2 != srcfield->size) {
/* possibly raise nonfatal exception here -> we only process the valid ones */
Expand All @@ -3950,29 +3961,29 @@ cob_intr_hex_to_char (cob_field *srcfield)

p = srcfield->data;
while (p < end) {
unsigned char src, dst;
src = *p++;
if (src >= 'A' && src <= 'F') {
dst = src - 'A' + 10;
} else if (src >= 'a' && src <= 'f') {
dst = src - 'a' + 10;
} else if (isdigit (src)) {
dst = COB_D2I (src);
unsigned char dst;
if (*p >= '0' && *p <= '9') {
dst = COB_D2I (*p);
} else if (*p >= 'A' && *p <= 'F') {
dst = *p - 'A' + 10;
} else if (*p >= 'a' && *p <= 'f') {
dst = *p - 'a' + 10;
} else {
dst = 0;
cob_set_exception (COB_EC_ARGUMENT_FUNCTION);
}
p++;
dst *= 16;
src = *p++;
if (src >= 'A' && src <= 'F') {
dst = dst + src - 'A' + 10;
} else if (src >= 'a' && src <= 'f') {
dst = dst + src - 'a' + 10;
} else if (isdigit (src)) {
dst = dst + COB_D2I (src);
if (*p >= '0' && *p <= '9') {
dst = dst + COB_D2I (*p);
} else if (*p >= 'A' && *p <= 'F') {
dst = dst + *p - 'A' + 10;
} else if (*p >= 'a' && *p <= 'f') {
dst = dst + *p - 'a' + 10;
} else {
cob_set_exception (COB_EC_ARGUMENT_FUNCTION);
}
p++;
*hex_char++ = dst;
}
return curr_field;
Expand Down Expand Up @@ -5925,9 +5936,10 @@ cob_intr_locale_date (const int offset, const int length,
p = srcfield->data;
indate = 0;
for (len = 0; len < 8; ++len, ++p) {
if (isdigit (*p)) {
indate *= 10;
indate += COB_D2I (*p);
/* note: as isdigit is locale-aware (slower and not what we want),
we use a range check instead */
if (*p >= '0' && *p <= '9') {
indate = indate * 10 + COB_D2I (*p);
} else {
goto derror;
}
Expand Down Expand Up @@ -6036,9 +6048,10 @@ cob_intr_locale_time (const int offset, const int length,
p = srcfield->data;
indate = 0;
for (len = 0; len < 6; ++len, ++p) {
if (isdigit (*p)) {
indate *= 10;
indate += COB_D2I (*p);
/* note: as isdigit is locale-aware (slower and not what we want),
we use a range check instead */
if (*p >= '0' && *p <= '9') {
indate = indate * 10 + COB_D2I (*p);
} else {
goto derror;
}
Expand Down Expand Up @@ -7239,7 +7252,6 @@ cob_init_intrinsic (cob_global *lptr)
calc_temp->calc_size = 256;
}


/* mpf_init2 length = ceil (log2 (10) * strlen (x)) */

mpz_init2 (cob_mexp, COB_MPZ_DEF);
Expand Down
67 changes: 34 additions & 33 deletions libcob/move.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,23 +242,17 @@ cob_binary_mset_uint64 (cob_field *f, cob_u64_t n)
static void
cob_move_alphanum_to_display (cob_field *f1, cob_field *f2)
{
unsigned char *p;
unsigned char *s1;
unsigned char *s2;
unsigned char *e1;
unsigned char *e2;
register unsigned char *s1 = f1->data;
register unsigned char *s2 = COB_FIELD_DATA (f2);
const unsigned char *e1 = s1 + f1->size;
const unsigned char *e2 = s2 + COB_FIELD_SIZE (f2);
const unsigned char dec_pt = COB_MODULE_PTR->decimal_point;
const unsigned char num_sep = COB_MODULE_PTR->numeric_separator;
int sign;
int count;
int size;
unsigned char c;
unsigned char dec_pt;
unsigned char num_sep;

/* Initialize */
s1 = f1->data;
e1 = s1 + f1->size;
s2 = COB_FIELD_DATA (f2);
e2 = s2 + COB_FIELD_SIZE (f2);
memset (f2->data, '0', f2->size);

/* Skip white spaces */
Expand All @@ -276,14 +270,16 @@ cob_move_alphanum_to_display (cob_field *f1, cob_field *f2)
}
}

dec_pt = COB_MODULE_PTR->decimal_point;
num_sep = COB_MODULE_PTR->numeric_separator;

/* Count the number of digits before decimal point */
count = 0;
for (p = s1; p < e1 && *p != dec_pt; ++p) {
if (isdigit (*p)) {
++count;
{
register unsigned char *p;
for (p = s1; p < e1 && *p != dec_pt; ++p) {
/* note: as isdigit is locale-aware (slower and not what we want),
we use a range check instead */
if (*p >= '0' && *p <= '9') {
++count;
}
}
}

Expand All @@ -293,23 +289,23 @@ cob_move_alphanum_to_display (cob_field *f1, cob_field *f2)
s2 += size - count;
} else {
while (count-- > size) {
while (!isdigit (*s1++)) {
;
while (*s1 < '0' || *s1 > '9') {
s1++;
}
s1++;
}
}

/* Move */
count = 0;
for (; s1 < e1 && s2 < e2; ++s1) {
c = *s1;
if (isdigit (c)) {
*s2++ = c;
} else if (c == dec_pt) {
if (*s1 >= '0' && *s1 <= '9') {
*s2++ = *s1;
} else if (*s1 == dec_pt) {
if (count++ > 0) {
goto error;
}
} else if (!(isspace (c) || c == num_sep)) {
} else if (!(isspace (*s1) || *s1 == num_sep)) {
goto error;
}
}
Expand Down Expand Up @@ -1964,11 +1960,11 @@ cob_get_int (cob_field *f)
{
cob_s64_t val = cob_binary_mget_sint64 (f);
if (COB_FIELD_SCALE (f) < 0) {
val *= cob_exp10_ll[(int)-COB_FIELD_SCALE (f)];
val *= cob_exp10_ll[(int)-COB_FIELD_SCALE (f)]; /* 999PP */
} else {
int inc;
for (inc = COB_FIELD_SCALE (f); inc > 0 && val; --inc) {
val /= 10;
val /= 10; /* 999[v9] */
}
}
return (int)val;
Expand Down Expand Up @@ -1997,11 +1993,11 @@ cob_get_llint (cob_field *f)
{
cob_s64_t val = cob_binary_mget_sint64 (f);
if (COB_FIELD_SCALE (f) < 0) {
val *= cob_exp10_ll[(int)-COB_FIELD_SCALE (f)];
val *= cob_exp10_ll[(int)-COB_FIELD_SCALE (f)]; /* 999PP */
} else {
int inc;
for (inc = COB_FIELD_SCALE (f); inc > 0 && val; --inc) {
val /= 10;
val /= 10; /* 999[v9] */
}
}
return val;
Expand Down Expand Up @@ -2619,14 +2615,16 @@ cob_get_s64_pic9 (void *mem, int len)
int sign = 1;

while (len-- > 1) {
if (isdigit (*p)) {
/* note: as isdigit is locale-aware (slower and not what we want),
we use a range check instead */
if (*p >= '0' && *p <= '9') {
val = val * 10 + COB_D2I (*p);
} else if (*p == '-') {
sign = -1;
}
p++;
}
if (isdigit (*p)) {
if (*p >= '0' && *p <= '9') {
val = val * 10 + COB_D2I (*p);
} else if (*p == '-') {
sign = -1;
Expand Down Expand Up @@ -2664,8 +2662,11 @@ cob_get_s64_pic9 (void *mem, int len)
}
val = val * 10 + COB_D2I (*p);
#endif
} else if (isdigit (*p & 0x3F)) {
val = val * 10 + COB_D2I (*p);
} else {
cob_u8_t dig_part = *p & 0x3F;
if (dig_part >= '0' && dig_part <= '9') {
val = val * 10 + COB_D2I (dig_part);
}
if (*p & 0x40) {
sign = -1;
}
Expand Down
Loading

0 comments on commit c6ea0f0

Please sign in to comment.