OpenCOBOL 1.1pre-rel
|
00001 /* 00002 * Copyright (C) 2001-2009 Keisuke Nishida 00003 * Copyright (C) 2007-2009 Roger While 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public License 00007 * as published by the Free Software Foundation; either version 2.1, 00008 * or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; see the file COPYING.LIB. If 00017 * not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor 00018 * Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 #include <ctype.h> 00027 #include <math.h> 00028 00029 #include "common.h" 00030 #include "coblocal.h" 00031 #include "move.h" 00032 #include "numeric.h" 00033 #include "byteswap.h" 00034 00035 #define COB_LIB_INCLUDE 00036 #include "codegen.h" 00037 00038 #define DECIMAL_NAN -128 00039 #define DECIMAL_CHECK(d1,d2) \ 00040 if (unlikely(d1->scale == DECIMAL_NAN || d2->scale == DECIMAL_NAN)) { \ 00041 d1->scale = DECIMAL_NAN; \ 00042 return; \ 00043 } 00044 00045 #define COB_MAX_BINARY 36 00046 00047 static const unsigned char packed_bytes[] = { 00048 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 00049 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 00050 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 00051 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 00052 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 00053 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 00054 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 00055 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 00056 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 00057 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99 00058 }; 00059 00060 static unsigned char *num_buff_ptr; 00061 static cob_decimal cob_d1; 00062 static cob_decimal cob_d2; 00063 static cob_decimal cob_d3; 00064 static cob_decimal cob_d4; 00065 static mpz_t cob_mexp; 00066 static mpz_t cob_mpzt; 00067 static mpz_t cob_mpze10[COB_MAX_BINARY]; 00068 static unsigned char packed_value[20]; 00069 00070 #ifdef COB_EXPERIMENTAL 00071 00072 #if GMP_NAIL_BITS != 0 00073 #error NAILS not supported 00074 #endif 00075 00076 #define COB_MAX_LL 9223372036854775807LL 00077 00078 static void 00079 mpz_set_ull (mpz_ptr dest, const unsigned long long val) 00080 { 00081 size_t size; 00082 00083 size = (val != 0); 00084 dest->_mp_d[0] = val & GMP_NUMB_MASK; 00085 #if GMP_LIMB_BITS < 64 00086 if (val > GMP_NUMB_MAX) { 00087 dest->_mp_d[1] = val >> GMP_NUMB_BITS; 00088 size = 2; 00089 } 00090 #endif 00091 dest->_mp_size = size; 00092 } 00093 00094 static void 00095 mpz_set_sll (mpz_ptr dest, const signed long long val) 00096 { 00097 unsigned long long vtmp; 00098 size_t size; 00099 00100 vtmp = (unsigned long long)(val >= 0 ? val : -val); 00101 size = (vtmp != 0); 00102 dest->_mp_d[0] = vtmp & GMP_NUMB_MASK; 00103 #if GMP_LIMB_BITS < 64 00104 if (vtmp > GMP_NUMB_MAX) { 00105 dest->_mp_d[1] = vtmp >> GMP_NUMB_BITS; 00106 size = 2; 00107 } 00108 #endif 00109 dest->_mp_size = (val >= 0) ? size : -size; 00110 } 00111 00112 static unsigned long long 00113 mpz_get_ull (const mpz_ptr src) 00114 { 00115 size_t size; 00116 00117 size = mpz_size (src); 00118 if (!size) { 00119 return 0; 00120 } 00121 #if GMP_LIMB_BITS > 32 00122 return (unsigned long long)src->_mp_d[0]; 00123 #else 00124 if (size < 2) { 00125 return (unsigned long long)src->_mp_d[0]; 00126 } 00127 return (unsigned long long)src->_mp_d[0] | 00128 ((unsigned long long)src->_mp_d[1] << GMP_NUMB_BITS); 00129 #endif 00130 } 00131 00132 static signed long long 00133 mpz_get_sll (const mpz_ptr src) 00134 { 00135 int size; 00136 unsigned long long vtmp; 00137 00138 size = src->_mp_size; 00139 if (!size) { 00140 return 0; 00141 } 00142 vtmp = (unsigned long long)src->_mp_d[0]; 00143 #if GMP_LIMB_BITS < 64 00144 if (mpz_size (src) > 1) { 00145 vtmp |= (unsigned long long)src->_mp_d[1] << GMP_NUMB_BITS; 00146 } 00147 #endif 00148 if (size > 0) { 00149 return (signed long long) vtmp & COB_MAX_LL; 00150 } 00151 return ~(((signed long long) vtmp - 1LL) & COB_MAX_LL); 00152 } 00153 00154 #endif /* COB_EXPERIMENTAL */ 00155 00156 static COB_INLINE void 00157 num_byte_memcpy (unsigned char *s1, const unsigned char *s2, size_t size) 00158 { 00159 do { 00160 *s1++ = *s2++; 00161 } while (--size); 00162 } 00163 00164 static long long 00165 cob_binary_get_int64 (const cob_field * const f) 00166 { 00167 long long n = 0; 00168 size_t fsiz = 8 - f->size; 00169 00170 /* Experimental code - not activated */ 00171 #if 0 00172 unsigned char *s; 00173 00174 if ((COB_FIELD_BINARY_SWAP (f) && !COB_FIELD_HAVE_SIGN (f)) || 00175 (!COB_FIELD_BINARY_SWAP (f) && COB_FIELD_HAVE_SIGN (f))) { 00176 s = (unsigned char *)&n + fsiz; 00177 } else { 00178 s = (unsigned char *)&n; 00179 } 00180 num_byte_memcpy (s, f->data, f->size); 00181 if (COB_FIELD_BINARY_SWAP (f)) { 00182 n = COB_BSWAP_64 (n); 00183 } 00184 if (COB_FIELD_HAVE_SIGN (f)) { 00185 n >>= 8 * fsiz; /* shift with sign */ 00186 } 00187 #endif 00188 #ifndef WORDS_BIGENDIAN 00189 if (COB_FIELD_BINARY_SWAP (f)) { 00190 if (COB_FIELD_HAVE_SIGN (f)) { 00191 num_byte_memcpy ((unsigned char *)&n, f->data, f->size); 00192 n = COB_BSWAP_64 (n); 00193 n >>= 8 * fsiz; /* shift with sign */ 00194 } else { 00195 num_byte_memcpy (((unsigned char *)&n) + fsiz, f->data, f->size); 00196 n = COB_BSWAP_64 (n); 00197 } 00198 } else { 00199 if (COB_FIELD_HAVE_SIGN (f)) { 00200 num_byte_memcpy (((unsigned char *)&n) + fsiz, f->data, f->size); 00201 n >>= 8 * fsiz; /* shift with sign */ 00202 } else { 00203 num_byte_memcpy ((unsigned char *)&n, f->data, f->size); 00204 } 00205 } 00206 #else /* WORDS_BIGENDIAN */ 00207 if (COB_FIELD_HAVE_SIGN (f)) { 00208 num_byte_memcpy ((unsigned char *)&n, f->data, f->size); 00209 n >>= 8 * fsiz; /* shift with sign */ 00210 } else { 00211 num_byte_memcpy (((unsigned char *)&n) + fsiz, f->data, f->size); 00212 } 00213 #endif /* WORDS_BIGENDIAN */ 00214 return n; 00215 } 00216 00217 static unsigned long long 00218 cob_binary_get_uint64 (const cob_field * const f) 00219 { 00220 unsigned long long n = 0; 00221 size_t fsiz = 8 - f->size; 00222 00223 #ifndef WORDS_BIGENDIAN 00224 if (COB_FIELD_BINARY_SWAP (f)) { 00225 num_byte_memcpy (((unsigned char *)&n) + fsiz, f->data, f->size); 00226 n = COB_BSWAP_64 (n); 00227 } else { 00228 num_byte_memcpy ((unsigned char *)&n, f->data, f->size); 00229 } 00230 #else /* WORDS_BIGENDIAN */ 00231 num_byte_memcpy (((unsigned char *)&n) + fsiz, f->data, f->size); 00232 #endif /* WORDS_BIGENDIAN */ 00233 return n; 00234 } 00235 00236 static void 00237 cob_binary_set_uint64 (cob_field *f, unsigned long long n) 00238 { 00239 #ifndef WORDS_BIGENDIAN 00240 unsigned char *s; 00241 00242 if (COB_FIELD_BINARY_SWAP (f)) { 00243 n = COB_BSWAP_64 (n); 00244 s = ((unsigned char *)&n) + 8 - f->size; 00245 } else { 00246 s = (unsigned char *)&n; 00247 } 00248 num_byte_memcpy (f->data, s, f->size); 00249 #else /* WORDS_BIGENDIAN */ 00250 num_byte_memcpy (f->data, ((unsigned char *)&n) + 8 - f->size, f->size); 00251 #endif /* WORDS_BIGENDIAN */ 00252 } 00253 00254 static void 00255 cob_binary_set_int64 (cob_field *f, long long n) 00256 { 00257 #ifndef WORDS_BIGENDIAN 00258 unsigned char *s; 00259 00260 if (COB_FIELD_BINARY_SWAP (f)) { 00261 n = COB_BSWAP_64 (n); 00262 s = ((unsigned char *)&n) + 8 - f->size; 00263 } else { 00264 s = (unsigned char *)&n; 00265 } 00266 num_byte_memcpy (f->data, s, f->size); 00267 #else /* WORDS_BIGENDIAN */ 00268 num_byte_memcpy (f->data, ((unsigned char *)&n) + 8 - f->size, f->size); 00269 #endif /* WORDS_BIGENDIAN */ 00270 } 00271 00272 /* 00273 * Decimal number 00274 */ 00275 00276 void 00277 cob_decimal_init (cob_decimal *d) 00278 { 00279 mpz_init2 (d->value, 256); 00280 d->scale = 0; 00281 } 00282 00283 /* Not used - comment out 00284 void 00285 cob_decimal_print (cob_decimal *d) 00286 { 00287 mpz_out_str (stdout, 10, d->value); 00288 if (d->scale) { 00289 fprintf (stdout, " * 10^%d", -d->scale); 00290 } 00291 fputs ("\n", stdout); 00292 } 00293 end comment out */ 00294 00295 /* d->value *= 10^n, d->scale += n */ 00296 static void 00297 shift_decimal (cob_decimal *d, const int n) 00298 { 00299 if (n == 0) { 00300 return; 00301 } 00302 if (n > 0) { 00303 mpz_ui_pow_ui (cob_mexp, 10, n); 00304 mpz_mul (d->value, d->value, cob_mexp); 00305 } else { 00306 mpz_ui_pow_ui (cob_mexp, 10, -n); 00307 mpz_tdiv_q (d->value, d->value, cob_mexp); 00308 } 00309 d->scale += n; 00310 } 00311 00312 static void 00313 align_decimal (cob_decimal *d1, cob_decimal *d2) 00314 { 00315 if (d1->scale < d2->scale) { 00316 shift_decimal (d1, d2->scale - d1->scale); 00317 } else if (d1->scale > d2->scale) { 00318 shift_decimal (d2, d1->scale - d2->scale); 00319 } 00320 } 00321 00322 /* 00323 * Decimal set/get 00324 */ 00325 00326 static void 00327 cob_decimal_set (cob_decimal *dst, const cob_decimal *src) 00328 { 00329 mpz_set (dst->value, src->value); 00330 dst->scale = src->scale; 00331 } 00332 00333 /* double */ 00334 00335 static void 00336 cob_decimal_set_double (cob_decimal *d, const double v) 00337 { 00338 mpz_set_d (d->value, v * 1.0e9); 00339 d->scale = 9; 00340 } 00341 00342 static double 00343 cob_decimal_get_double (cob_decimal *d) 00344 { 00345 double v; 00346 int n; 00347 00348 v = mpz_get_d (d->value); 00349 n = d->scale; 00350 for (; n > 0; n--) { 00351 v /= 10; 00352 } 00353 for (; n < 0; n++) { 00354 v *= 10; 00355 } 00356 return v; 00357 } 00358 00359 /* DISPLAY */ 00360 00361 static void 00362 cob_decimal_set_display (cob_decimal *d, cob_field *f) 00363 { 00364 unsigned char *data; 00365 size_t size; 00366 int sign; 00367 unsigned int n; 00368 00369 data = COB_FIELD_DATA (f); 00370 size = COB_FIELD_SIZE (f); 00371 if (unlikely(*data == 255)) { 00372 mpz_ui_pow_ui (d->value, 10, size); 00373 d->scale = COB_FIELD_SCALE(f); 00374 return; 00375 } 00376 if (unlikely(*data == 0)) { 00377 mpz_ui_pow_ui (d->value, 10, size); 00378 mpz_neg (d->value, d->value); 00379 d->scale = COB_FIELD_SCALE(f); 00380 return; 00381 } 00382 sign = cob_get_sign (f); 00383 /* skip leading zeros */ 00384 while (size > 1 && *data == '0') { 00385 size--; 00386 data++; 00387 } 00388 00389 /* set value */ 00390 if (size < 10) { 00391 n = 0; 00392 while (size--) { 00393 n = n * 10 + cob_d2i (*data++); 00394 } 00395 mpz_set_ui (d->value, n); 00396 } else { 00397 memcpy (num_buff_ptr, data, size); 00398 num_buff_ptr[size] = 0; 00399 mpz_set_str (d->value, (char *)num_buff_ptr, 10); 00400 } 00401 00402 /* set sign and scale */ 00403 if (sign < 0) { 00404 mpz_neg (d->value, d->value); 00405 } 00406 d->scale = COB_FIELD_SCALE(f); 00407 cob_put_sign (f, sign); 00408 } 00409 00410 static int 00411 cob_decimal_get_display (cob_decimal *d, cob_field *f, const int opt) 00412 { 00413 unsigned char *data; 00414 size_t size; 00415 int diff; 00416 int sign; 00417 00418 /* build string */ 00419 sign = mpz_sgn (d->value); 00420 mpz_abs (d->value, d->value); 00421 mpz_get_str ((char *)num_buff_ptr, 10, d->value); 00422 size = strlen ((char *)num_buff_ptr); 00423 00424 /* store number */ 00425 data = COB_FIELD_DATA (f); 00426 diff = (int)(COB_FIELD_SIZE (f) - size); 00427 if (unlikely(diff < 0)) { 00428 /* overflow */ 00429 cob_set_exception (COB_EC_SIZE_OVERFLOW); 00430 00431 /* if the statement has ON SIZE ERROR or NOT ON SIZE ERROR, 00432 then throw an exception */ 00433 if (opt & COB_STORE_KEEP_ON_OVERFLOW) { 00434 return cob_exception_code; 00435 } 00436 00437 /* othersize, truncate digits */ 00438 memcpy (data, num_buff_ptr - diff, COB_FIELD_SIZE (f)); 00439 } else { 00440 /* no overflow */ 00441 memset (data, '0', (size_t)diff); 00442 memcpy (data + diff, num_buff_ptr, size); 00443 } 00444 00445 cob_put_sign (f, sign); 00446 return 0; 00447 } 00448 00449 /* BINARY */ 00450 00451 static void 00452 cob_decimal_set_binary (cob_decimal *d, cob_field *f) 00453 { 00454 #ifdef COB_LI_IS_LL 00455 if (COB_FIELD_HAVE_SIGN (f)) { 00456 mpz_set_si (d->value, cob_binary_get_int64 (f)); 00457 } else { 00458 mpz_set_ui (d->value, cob_binary_get_uint64 (f)); 00459 } 00460 #elif defined(COB_EXPERIMENTAL) 00461 if (COB_FIELD_HAVE_SIGN (f)) { 00462 mpz_set_sll (d->value, cob_binary_get_int64 (f)); 00463 } else { 00464 mpz_set_ull (d->value, cob_binary_get_uint64 (f)); 00465 } 00466 #else 00467 size_t negative = 0; 00468 unsigned long long uval; 00469 long long val; 00470 00471 if (f->size <= 4) { 00472 if (COB_FIELD_HAVE_SIGN (f)) { 00473 mpz_set_si (d->value, (int)cob_binary_get_int64 (f)); 00474 } else { 00475 mpz_set_ui (d->value, (unsigned int) cob_binary_get_uint64 (f)); 00476 } 00477 } else { 00478 if (COB_FIELD_HAVE_SIGN (f)) { 00479 val = cob_binary_get_int64 (f); 00480 if (val < 0) { 00481 negative = 1; 00482 val = -val; 00483 } 00484 mpz_set_ui (d->value, (unsigned int)((val & 0x7FFFFFFF00000000LL)>> 32)); 00485 mpz_mul_2exp (d->value, d->value, 32); 00486 mpz_add_ui (d->value, d->value, (unsigned int)(val & 0xffffffff)); 00487 if (negative) { 00488 mpz_neg (d->value, d->value); 00489 } 00490 } else { 00491 uval = cob_binary_get_uint64 (f); 00492 mpz_set_ui (d->value, (unsigned int)(uval >> 32)); 00493 mpz_mul_2exp (d->value, d->value, 32); 00494 mpz_add_ui (d->value, d->value, (unsigned int)(uval & 0xffffffff)); 00495 } 00496 } 00497 #endif 00498 d->scale = COB_FIELD_SCALE(f); 00499 } 00500 00501 static int 00502 cob_decimal_get_binary (cob_decimal *d, cob_field *f, const int opt) 00503 { 00504 size_t overflow; 00505 size_t digits; 00506 size_t sign; 00507 size_t bitnum; 00508 #if !defined(COB_EXPERIMENTAL) && !defined(COB_LI_IS_LL) 00509 long long llval; 00510 unsigned long long ullval; 00511 unsigned int lo; 00512 #endif 00513 00514 if (unlikely(mpz_size (d->value) == 0)) { 00515 memset (f->data, 0, f->size); 00516 return 0; 00517 } 00518 overflow = 0; 00519 digits = COB_FIELD_DIGITS(f); 00520 if (COB_FIELD_HAVE_SIGN (f)) { 00521 sign = 1; 00522 } else { 00523 sign = 0; 00524 if (mpz_sgn (d->value) < 0) { 00525 mpz_abs (d->value, d->value); 00526 } 00527 } 00528 bitnum = (f->size * 8) - sign; 00529 if (unlikely(mpz_sizeinbase (d->value, 2) > bitnum)) { 00530 if (opt & COB_STORE_KEEP_ON_OVERFLOW) { 00531 goto overflow; 00532 } 00533 overflow = 1; 00534 /* TRUNC_ON_OVERFLOW is only set for binary_truncate */ 00535 if (opt & COB_STORE_TRUNC_ON_OVERFLOW) { 00536 mpz_tdiv_r (d->value, d->value, cob_mpze10[digits]); 00537 /* 00538 } 00539 */ 00540 /* RXW */ 00541 } else { 00542 mpz_fdiv_r_2exp (d->value, d->value, (f->size * 8)); 00543 } 00544 } else if (opt && cob_current_module->flag_binary_truncate) { 00545 if (mpz_cmpabs (d->value, cob_mpze10[digits]) >= 0) { 00546 /* overflow */ 00547 if (opt & COB_STORE_KEEP_ON_OVERFLOW) { 00548 goto overflow; 00549 } 00550 overflow = 1; 00551 /* TRUNC_ON_OVERFLOW is only set for binary_truncate */ 00552 if (opt & COB_STORE_TRUNC_ON_OVERFLOW) { 00553 mpz_tdiv_r (d->value, d->value, cob_mpze10[digits]); 00554 /* 00555 } 00556 */ 00557 /* RXW */ 00558 } else { 00559 mpz_fdiv_r_2exp (d->value, d->value, (f->size * 8)); 00560 } 00561 } 00562 } 00563 #ifdef COB_LI_IS_LL 00564 if (!sign || overflow) { 00565 cob_binary_set_uint64 (f, mpz_get_ui (d->value)); 00566 } else { 00567 cob_binary_set_int64 (f, mpz_get_si (d->value)); 00568 } 00569 #elif defined(COB_EXPERIMENTAL) 00570 if (!sign || overflow) { 00571 cob_binary_set_uint64 (f, mpz_get_ull (d->value)); 00572 } else { 00573 cob_binary_set_int64 (f, mpz_get_sll (d->value)); 00574 } 00575 #else 00576 if (f->size <= 4) { 00577 if (!sign || overflow) { 00578 cob_binary_set_uint64 (f, (unsigned long long)mpz_get_ui (d->value)); 00579 } else { 00580 cob_binary_set_int64 (f, (long long)mpz_get_si (d->value)); 00581 } 00582 } else { 00583 mpz_fdiv_r_2exp (cob_mpzt, d->value, 32); 00584 mpz_fdiv_q_2exp (d->value, d->value, 32); 00585 lo = mpz_get_ui (cob_mpzt); 00586 00587 if (!sign || overflow) { 00588 ullval = mpz_get_ui (d->value); 00589 ullval = (ullval << 32) | lo; 00590 cob_binary_set_uint64 (f, ullval); 00591 } else { 00592 llval = mpz_get_si (d->value); 00593 llval = (llval << 32) | lo; 00594 cob_binary_set_int64 (f, llval); 00595 } 00596 } 00597 #endif 00598 if (!overflow) { 00599 return 0; 00600 } 00601 00602 overflow: 00603 cob_set_exception (COB_EC_SIZE_OVERFLOW); 00604 return cob_exception_code; 00605 } 00606 00607 /* PACKED-DECIMAL */ 00608 00609 static int 00610 cob_packed_get_sign (const cob_field *f) 00611 { 00612 unsigned char *p; 00613 00614 if (!COB_FIELD_HAVE_SIGN (f)) { 00615 return 0; 00616 } 00617 p = f->data + f->size - 1; 00618 return ((*p & 0x0f) == 0x0d) ? -1 : 1; 00619 } 00620 00621 static void 00622 cob_add_packed (cob_field *f, int val) 00623 { 00624 unsigned char *p; 00625 int sign; 00626 int ndigs; 00627 int tval; 00628 int carry = 0; 00629 unsigned int msn; 00630 unsigned int subtr = 0; 00631 unsigned int zeroes = 0; 00632 unsigned int origdigs; 00633 00634 ndigs = COB_FIELD_DIGITS(f) - COB_FIELD_SCALE(f); 00635 if (ndigs <= 0) { 00636 return; 00637 } 00638 sign = cob_packed_get_sign (f); 00639 msn = 1 - (COB_FIELD_SCALE(f) % 2); 00640 00641 /* -x +v = -(x - v), -x -v = -(x + v) */ 00642 if (sign < 0) { 00643 val = -val; 00644 } 00645 if (val < 0) { 00646 val = -val; 00647 subtr = 1; 00648 } 00649 p = f->data + (ndigs / 2) - (1 - msn); 00650 origdigs = ndigs; 00651 while (ndigs--) { 00652 if (!msn) { 00653 tval = *p & 0x0f; 00654 } else { 00655 tval = (*p & 0xf0) >> 4; 00656 } 00657 if (val) { 00658 carry += (val % 10); 00659 val /= 10; 00660 } 00661 if (subtr) { 00662 tval -= carry; 00663 if (tval < 0) { 00664 tval += 10; 00665 carry = 1; 00666 } else { 00667 carry = 0; 00668 } 00669 } else { 00670 tval += carry; 00671 if (tval > 9) { 00672 tval %= 10; 00673 carry = 1; 00674 } else { 00675 carry = 0; 00676 } 00677 } 00678 if (tval == 0) { 00679 zeroes++; 00680 } 00681 if (!msn) { 00682 *p = (*p & 0xf0) | tval; 00683 msn = 1; 00684 } else { 00685 *p = (*p & 0x0f) | (tval << 4); 00686 msn = 0; 00687 p--; 00688 } 00689 } 00690 if (sign) { 00691 p = f->data + f->size - 1; 00692 if (origdigs == zeroes) { 00693 *p = (*p & 0xf0) | 0x0c; 00694 } else if (subtr && carry) { 00695 sign = -sign; 00696 if (sign < 0) { 00697 *p = (*p & 0xf0) | 0x0d; 00698 } else { 00699 *p = (*p & 0xf0) | 0x0c; 00700 } 00701 } 00702 } 00703 } 00704 00705 static void 00706 cob_decimal_set_packed (cob_decimal *d, cob_field *f) 00707 { 00708 unsigned char *p; 00709 int digits; 00710 int sign; 00711 unsigned int val; 00712 unsigned int valseen; 00713 00714 p = f->data; 00715 /* Fixme */ 00716 digits = COB_FIELD_DIGITS (f); 00717 sign = cob_packed_get_sign (f); 00718 00719 if (digits % 2 == 0) { 00720 val = *p & 0x0f; 00721 digits--; 00722 p++; 00723 } else { 00724 val = 0; 00725 } 00726 00727 if (COB_FIELD_DIGITS(f) < 10) { 00728 while (digits > 1) { 00729 if (val) { 00730 val *= 100; 00731 } 00732 if (*p) { 00733 val += ((*p >> 4) * 10) + (*p & 0x0f); 00734 } 00735 digits -= 2; 00736 p++; 00737 } 00738 if (val) { 00739 val *= 10; 00740 } 00741 val += *p >> 4; 00742 mpz_set_ui (d->value, val); 00743 } else { 00744 valseen = 0; 00745 mpz_set_ui (d->value, val); 00746 if (val) { 00747 valseen = 1; 00748 } 00749 while (digits > 1) { 00750 if (valseen) { 00751 mpz_mul_ui (d->value, d->value, 100); 00752 } 00753 if (*p) { 00754 mpz_add_ui (d->value, d->value, 00755 (*p >> 4) * 10 + (*p & 0x0f)); 00756 valseen = 1; 00757 } 00758 digits -= 2; 00759 p++; 00760 } 00761 if (valseen) { 00762 mpz_mul_ui (d->value, d->value, 10); 00763 } 00764 mpz_add_ui (d->value, d->value, (*p >> 4)); 00765 } 00766 00767 if (sign < 0) { 00768 mpz_neg (d->value, d->value); 00769 } 00770 d->scale = COB_FIELD_SCALE(f); 00771 } 00772 00773 static int 00774 cob_decimal_get_packed (cob_decimal *d, cob_field *f, const int opt) 00775 { 00776 unsigned char *data; 00777 unsigned char *p; 00778 unsigned char *q; 00779 size_t size; 00780 size_t n; 00781 size_t i; 00782 int diff; 00783 int sign; 00784 int digits; 00785 unsigned char x; 00786 00787 /* build string */ 00788 sign = mpz_sgn (d->value); 00789 mpz_abs (d->value, d->value); 00790 mpz_get_str ((char *)num_buff_ptr, 10, d->value); 00791 size = strlen ((char *)num_buff_ptr); 00792 00793 /* store number */ 00794 data = f->data; 00795 /* Fixme */ 00796 digits = COB_FIELD_DIGITS(f); 00797 q = num_buff_ptr; 00798 diff = (int)(digits - size); 00799 if (diff < 0) { 00800 /* overflow */ 00801 cob_set_exception (COB_EC_SIZE_OVERFLOW); 00802 00803 /* if the statement has ON SIZE ERROR or NOT ON SIZE ERROR, 00804 then throw an exception */ 00805 if (opt & COB_STORE_KEEP_ON_OVERFLOW) { 00806 return cob_exception_code; 00807 } 00808 q += size - digits; 00809 size = digits; 00810 } 00811 memset (data, 0, f->size); 00812 p = data + (digits / 2) - (size / 2); 00813 diff = 1 - (int)(size % 2); 00814 for (i = diff, n = 0; i < size + diff; i++, n++) { 00815 x = cob_d2i (q[n]); 00816 if (i % 2 == 0) { 00817 *p = x << 4; 00818 } else { 00819 *p++ |= x; 00820 } 00821 } 00822 00823 p = f->data + f->size - 1; 00824 if (!COB_FIELD_HAVE_SIGN (f)) { 00825 *p = (*p & 0xf0) | 0x0f; 00826 } else if (sign < 0) { 00827 *p = (*p & 0xf0) | 0x0d; 00828 } else { 00829 *p = (*p & 0xf0) | 0x0c; 00830 } 00831 00832 return 0; 00833 } 00834 00835 void 00836 cob_set_packed_zero (cob_field *f) 00837 { 00838 memset (f->data, 0, f->size); 00839 if (!COB_FIELD_HAVE_SIGN (f)) { 00840 *(f->data + f->size - 1) = 0x0f; 00841 } else { 00842 *(f->data + f->size - 1) = 0x0c; 00843 } 00844 } 00845 00846 void 00847 cob_set_packed_int (cob_field *f, const int val) 00848 { 00849 unsigned char *p; 00850 size_t sign = 0; 00851 int n; 00852 00853 if (val < 0) { 00854 n = -val; 00855 sign = 1; 00856 } else { 00857 n = val; 00858 } 00859 memset (f->data, 0, f->size); 00860 p = f->data + f->size - 1; 00861 *p = (n % 10) << 4; 00862 if (!COB_FIELD_HAVE_SIGN (f)) { 00863 *p |= 0x0f; 00864 } else if (sign) { 00865 *p |= 0x0d; 00866 } else { 00867 *p |= 0x0c; 00868 } 00869 n /= 10; 00870 p--; 00871 for (; n && p >= f->data; n /= 100, p--) { 00872 *p = packed_bytes[n % 100]; 00873 } 00874 /* Fixme */ 00875 if ((COB_FIELD_DIGITS(f) % 2) == 0) { 00876 *(f->data) &= 0x0f; 00877 } 00878 } 00879 00880 /* General field */ 00881 00882 void 00883 cob_decimal_set_field (cob_decimal *d, cob_field *f) 00884 { 00885 double dval; 00886 float fval; 00887 00888 switch (COB_FIELD_TYPE (f)) { 00889 case COB_TYPE_NUMERIC_BINARY: 00890 cob_decimal_set_binary (d, f); 00891 break; 00892 case COB_TYPE_NUMERIC_PACKED: 00893 cob_decimal_set_packed (d, f); 00894 break; 00895 case COB_TYPE_NUMERIC_FLOAT: 00896 memcpy ((ucharptr)&fval, f->data, sizeof(float)); 00897 cob_decimal_set_double (d, (double)fval); 00898 break; 00899 case COB_TYPE_NUMERIC_DOUBLE: 00900 memcpy ((ucharptr)&dval, f->data, sizeof(double)); 00901 cob_decimal_set_double (d, dval); 00902 break; 00903 default: 00904 cob_decimal_set_display (d, f); 00905 break; 00906 } 00907 } 00908 00909 int 00910 cob_decimal_get_field (cob_decimal *d, cob_field *f, const int opt) 00911 { 00912 cob_field temp; 00913 cob_field_attr attr; 00914 double val; 00915 float fval; 00916 int sign; 00917 unsigned char data[64]; 00918 00919 if (unlikely(d->scale == DECIMAL_NAN)) { 00920 cob_set_exception (COB_EC_SIZE_OVERFLOW); 00921 return cob_exception_code; 00922 } 00923 00924 /* work copy */ 00925 if (d != &cob_d1) { 00926 cob_decimal_set (&cob_d1, d); 00927 d = &cob_d1; 00928 } 00929 00930 /* rounding */ 00931 if (opt & COB_STORE_ROUND) { 00932 if (COB_FIELD_SCALE(f) < d->scale) { 00933 sign = mpz_sgn (d->value); 00934 if (sign != 0) { 00935 shift_decimal (d, COB_FIELD_SCALE(f) - d->scale + 1); 00936 if (sign > 0) { 00937 mpz_add_ui (d->value, d->value, 5); 00938 } else { 00939 mpz_sub_ui (d->value, d->value, 5); 00940 } 00941 } 00942 } 00943 } 00944 00945 /* append or truncate decimal digits */ 00946 shift_decimal (d, COB_FIELD_SCALE(f) - d->scale); 00947 00948 /* store number */ 00949 switch (COB_FIELD_TYPE (f)) { 00950 case COB_TYPE_NUMERIC_BINARY: 00951 return cob_decimal_get_binary (d, f, opt); 00952 case COB_TYPE_NUMERIC_PACKED: 00953 return cob_decimal_get_packed (d, f, opt); 00954 case COB_TYPE_NUMERIC_DISPLAY: 00955 return cob_decimal_get_display (d, f, opt); 00956 case COB_TYPE_NUMERIC_FLOAT: 00957 fval = (float) cob_decimal_get_double (d); 00958 memcpy (f->data, (ucharptr)&fval, sizeof (float)); 00959 return 0; 00960 case COB_TYPE_NUMERIC_DOUBLE: 00961 val = cob_decimal_get_double (d); 00962 memcpy (f->data, (ucharptr)&val, sizeof (double)); 00963 return 0; 00964 default: 00965 COB_ATTR_INIT (COB_TYPE_NUMERIC_DISPLAY, COB_FIELD_DIGITS(f), 00966 COB_FIELD_SCALE(f), COB_FLAG_HAVE_SIGN, NULL); 00967 temp.size = COB_FIELD_DIGITS(f); 00968 temp.data = data; 00969 temp.attr = &attr; 00970 if (cob_decimal_get_display (d, &temp, opt) == 0) { 00971 cob_move (&temp, f); 00972 } 00973 return cob_exception_code; 00974 } 00975 } 00976 00977 /* 00978 * Decimal arithmetic 00979 */ 00980 00981 void 00982 cob_decimal_add (cob_decimal *d1, cob_decimal *d2) 00983 { 00984 DECIMAL_CHECK (d1, d2); 00985 align_decimal (d1, d2); 00986 mpz_add (d1->value, d1->value, d2->value); 00987 } 00988 00989 void 00990 cob_decimal_sub (cob_decimal *d1, cob_decimal *d2) 00991 { 00992 DECIMAL_CHECK (d1, d2); 00993 align_decimal (d1, d2); 00994 mpz_sub (d1->value, d1->value, d2->value); 00995 } 00996 00997 void 00998 cob_decimal_mul (cob_decimal *d1, cob_decimal *d2) 00999 { 01000 DECIMAL_CHECK (d1, d2); 01001 d1->scale += d2->scale; 01002 mpz_mul (d1->value, d1->value, d2->value); 01003 } 01004 01005 void 01006 cob_decimal_div (cob_decimal *d1, cob_decimal *d2) 01007 { 01008 DECIMAL_CHECK (d1, d2); 01009 01010 /* check for division by zero */ 01011 if (unlikely(mpz_sgn (d2->value) == 0)) { 01012 d1->scale = DECIMAL_NAN; 01013 cob_set_exception (COB_EC_SIZE_ZERO_DIVIDE); 01014 return; 01015 } 01016 if (unlikely(mpz_sgn (d1->value) == 0)) { 01017 d1->scale = 0; 01018 return; 01019 } 01020 d1->scale -= d2->scale; 01021 shift_decimal (d1, 37 + ((d1->scale < 0) ? -d1->scale : 0)); 01022 mpz_tdiv_q (d1->value, d1->value, d2->value); 01023 } 01024 01025 void 01026 cob_decimal_pow (cob_decimal *d1, cob_decimal *d2) 01027 { 01028 unsigned int n; 01029 01030 DECIMAL_CHECK (d1, d2); 01031 01032 if (d2->scale == 0 && mpz_fits_ulong_p (d2->value)) { 01033 n = mpz_get_ui (d2->value); 01034 mpz_pow_ui (d1->value, d1->value, n); 01035 d1->scale *= n; 01036 } else { 01037 cob_decimal_set_double (d1, pow (cob_decimal_get_double (d1), 01038 cob_decimal_get_double (d2))); 01039 } 01040 } 01041 01042 int 01043 cob_decimal_cmp (cob_decimal *d1, cob_decimal *d2) 01044 { 01045 align_decimal (d1, d2); 01046 return mpz_cmp (d1->value, d2->value); 01047 } 01048 01049 /* 01050 * Optimized arithmetic for DISPLAY 01051 */ 01052 01053 static int 01054 display_add_int (unsigned char *data, const size_t size, unsigned int n) 01055 { 01056 unsigned char *sp; 01057 size_t carry = 0; 01058 int i; 01059 int is; 01060 01061 sp = data + size; 01062 while (n > 0) { 01063 i = n % 10; 01064 n /= 10; 01065 01066 /* check for overflow */ 01067 if (unlikely(--sp < data)) { 01068 if (!cob_current_module->flag_binary_truncate) { 01069 return 0; 01070 } 01071 return 1; 01072 } 01073 01074 /* perform addition */ 01075 is = (*sp & 0x0F) + i + carry; 01076 if (is > 9) { 01077 carry = 1; 01078 *sp = '0' + (is % 10); 01079 } else { 01080 carry = 0; 01081 *sp = '0' + is; 01082 } 01083 } 01084 if (carry == 0) { 01085 return 0; 01086 } 01087 01088 /* carry up */ 01089 while (--sp >= data) { 01090 if ((*sp += 1) <= '9') { 01091 return 0; 01092 } 01093 *sp = '0'; 01094 } 01095 if (!cob_current_module->flag_binary_truncate) { 01096 return 0; 01097 } 01098 return 1; 01099 } 01100 01101 static int 01102 display_sub_int (unsigned char *data, const size_t size, unsigned int n) 01103 { 01104 unsigned char *sp; 01105 size_t carry = 0; 01106 int i; 01107 01108 sp = data + size; 01109 while (n > 0) { 01110 i = n % 10; 01111 n /= 10; 01112 01113 /* check for overflow */ 01114 if (unlikely(--sp < data)) { 01115 return 1; 01116 } 01117 01118 /* perform subtraction */ 01119 if ((*sp -= i + carry) < '0') { 01120 carry = 1; 01121 *sp += 10; 01122 } else { 01123 carry = 0; 01124 } 01125 } 01126 if (carry == 0) { 01127 return 0; 01128 } 01129 01130 /* carry up */ 01131 while (--sp >= data) { 01132 if ((*sp -= 1) >= '0') { 01133 return 0; 01134 } 01135 *sp = '9'; 01136 } 01137 return 1; 01138 } 01139 01140 static int 01141 cob_display_add_int (cob_field *f, int n) 01142 { 01143 unsigned char *data; 01144 size_t osize; 01145 size_t i; 01146 size_t size; 01147 int scale; 01148 int sign; 01149 unsigned char tfield[64]; 01150 01151 data = COB_FIELD_DATA (f); 01152 size = COB_FIELD_SIZE (f); 01153 scale = COB_FIELD_SCALE (f); 01154 sign = cob_get_sign (f); 01155 osize = size; 01156 memcpy (tfield, data, osize); 01157 /* -x + n = -(x - n) */ 01158 if (sign < 0) { 01159 n = -n; 01160 } 01161 01162 if (unlikely(scale < 0)) { 01163 /* PIC 9(n)P(m) */ 01164 if (-scale < 10) { 01165 while (scale++) { 01166 n /= 10; 01167 } 01168 } else { 01169 n = 0; 01170 } 01171 } else { 01172 /* PIC 9(n)V9(m) */ 01173 size -= scale; 01174 /* Following can never be true as size is unsigned ?? */ 01175 /* Comment out 01176 if (size < 0) { 01177 cob_put_sign (f, sign); 01178 goto overflow; 01179 } 01180 */ 01181 } 01182 01183 if (n > 0) { 01184 /* add n to the field */ 01185 if (display_add_int (data, size, n) != 0) { 01186 /* if there was an overflow, recover the last value */ 01187 memcpy (data, tfield, osize); 01188 goto overflow; 01189 } 01190 } else if (n < 0) { 01191 /* subtract n from the field */ 01192 if (display_sub_int (data, size, -n) != 0) { 01193 for (i = 0; i < size; i++) { 01194 data[i] = cob_i2d (9 - cob_d2i (data[i])); 01195 } 01196 display_add_int (data, size, 1); 01197 sign = -sign; 01198 } 01199 } 01200 01201 cob_put_sign (f, sign); 01202 return 0; 01203 01204 overflow: 01205 cob_put_sign (f, sign); 01206 cob_set_exception (COB_EC_SIZE_OVERFLOW); 01207 return cob_exception_code; 01208 } 01209 01210 /* 01211 * Convenience functions 01212 */ 01213 01214 int 01215 cob_add (cob_field *f1, cob_field *f2, const int opt) 01216 { 01217 cob_decimal_set_field (&cob_d1, f1); 01218 cob_decimal_set_field (&cob_d2, f2); 01219 cob_decimal_add (&cob_d1, &cob_d2); 01220 return cob_decimal_get_field (&cob_d1, f1, opt); 01221 } 01222 01223 int 01224 cob_sub (cob_field *f1, cob_field *f2, const int opt) 01225 { 01226 cob_decimal_set_field (&cob_d1, f1); 01227 cob_decimal_set_field (&cob_d2, f2); 01228 cob_decimal_sub (&cob_d1, &cob_d2); 01229 return cob_decimal_get_field (&cob_d1, f1, opt); 01230 } 01231 01232 int 01233 cob_add_int (cob_field *f, const int n) 01234 { 01235 if (unlikely(n == 0)) { 01236 return 0; 01237 } 01238 switch (COB_FIELD_TYPE (f)) { 01239 case COB_TYPE_NUMERIC_DISPLAY: 01240 return cob_display_add_int (f, n); 01241 case COB_TYPE_NUMERIC_PACKED: 01242 cob_add_packed (f, n); 01243 return 0; 01244 default: 01245 /* not optimized */ 01246 cob_decimal_set_field (&cob_d1, f); 01247 mpz_set_si (cob_d2.value, n); 01248 cob_d2.scale = 0; 01249 if (cob_d1.scale) { 01250 mpz_ui_pow_ui (cob_mexp, 10, (unsigned int)cob_d1.scale); 01251 mpz_mul (cob_d2.value, cob_d2.value, cob_mexp); 01252 cob_d2.scale = cob_d1.scale; 01253 } 01254 mpz_add (cob_d1.value, cob_d1.value, cob_d2.value); 01255 return cob_decimal_get_field (&cob_d1, f, 0); 01256 } 01257 } 01258 01259 int 01260 cob_sub_int (cob_field *f, const int n) 01261 { 01262 if (unlikely(n == 0)) { 01263 return 0; 01264 } 01265 return cob_add_int (f, -n); 01266 } 01267 01268 int 01269 cob_div_quotient (cob_field *dividend, cob_field *divisor, 01270 cob_field *quotient, const int opt) 01271 { 01272 int ret; 01273 01274 cob_decimal_set_field (&cob_d1, dividend); 01275 cob_decimal_set_field (&cob_d2, divisor); 01276 cob_decimal_set (&cob_d3, &cob_d1); 01277 01278 /* compute quotient */ 01279 cob_decimal_div (&cob_d1, &cob_d2); 01280 if (cob_d1.scale == DECIMAL_NAN) { 01281 cob_d3.scale = DECIMAL_NAN; 01282 return cob_exception_code; 01283 } 01284 01285 /* set quotient */ 01286 cob_decimal_set (&cob_d4, &cob_d1); 01287 ret = cob_decimal_get_field (&cob_d1, quotient, opt); 01288 01289 /* truncate digits from the quotient */ 01290 shift_decimal (&cob_d4, COB_FIELD_SCALE(quotient) - cob_d4.scale); 01291 01292 /* compute remainder */ 01293 cob_decimal_mul (&cob_d4, &cob_d2); 01294 cob_decimal_sub (&cob_d3, &cob_d4); 01295 01296 return ret; 01297 } 01298 01299 int 01300 cob_div_remainder (cob_field *fld_remainder, const int opt) 01301 { 01302 return cob_decimal_get_field (&cob_d3, fld_remainder, opt); 01303 } 01304 01305 int 01306 cob_cmp_int (cob_field *f1, const int n) 01307 { 01308 cob_decimal_set_field (&cob_d1, f1); 01309 mpz_set_si (cob_d2.value, n); 01310 cob_d2.scale = 0; 01311 return cob_decimal_cmp (&cob_d1, &cob_d2); 01312 } 01313 01314 int 01315 cob_cmp_uint (cob_field *f1, const unsigned int n) 01316 { 01317 cob_decimal_set_field (&cob_d1, f1); 01318 mpz_set_ui (cob_d2.value, n); 01319 cob_d2.scale = 0; 01320 return cob_decimal_cmp (&cob_d1, &cob_d2); 01321 } 01322 01323 int 01324 cob_numeric_cmp (cob_field *f1, cob_field *f2) 01325 { 01326 cob_decimal_set_field (&cob_d1, f1); 01327 cob_decimal_set_field (&cob_d2, f2); 01328 return cob_decimal_cmp (&cob_d1, &cob_d2); 01329 } 01330 01331 int 01332 cob_cmp_packed (cob_field *f, int n) 01333 { 01334 static int lastval = 0; 01335 01336 unsigned char *p; 01337 size_t size; 01338 size_t inc = 0; 01339 int sign; 01340 unsigned char val1[20]; 01341 01342 sign = cob_packed_get_sign (f); 01343 /* Field positive, value negative */ 01344 if (sign >= 0 && n < 0) { 01345 return 1; 01346 } 01347 /* Field negative, value positive */ 01348 if (sign < 0 && n >= 0) { 01349 return -1; 01350 } 01351 /* Both positive or both negative */ 01352 p = f->data; 01353 for (size = 0; size < 20; size++) { 01354 if (size < 20 - f->size) { 01355 val1[size] = 0; 01356 } else { 01357 val1[size] = p[inc++]; 01358 } 01359 } 01360 val1[19] &= 0xf0; 01361 if ((COB_FIELD_DIGITS(f) % 2) == 0) { 01362 val1[20 - f->size] &= 0x0f; 01363 } 01364 if (n != lastval) { 01365 lastval = n; 01366 if (n < 0) { 01367 n = -n; 01368 } 01369 memset (&packed_value[14], 0, 6); 01370 if (n) { 01371 p = &packed_value[19]; 01372 *p = (n % 10) << 4; 01373 p--; 01374 n /= 10; 01375 for (; n;) { 01376 size = n % 100; 01377 *p = (unsigned char)((size % 10) | ((size / 10) << 4)); 01378 n /= 100; 01379 p--; 01380 } 01381 } 01382 } 01383 for (size = 0; size < 20; size++) { 01384 if (val1[size] != packed_value[size]) { 01385 if (sign < 0) { 01386 return packed_value[size] - val1[size]; 01387 } else { 01388 return val1[size] - packed_value[size]; 01389 } 01390 } 01391 } 01392 return 0; 01393 } 01394 01395 void 01396 cob_init_numeric (void) 01397 { 01398 size_t i; 01399 01400 cob_decimal_init (&cob_d1); 01401 cob_decimal_init (&cob_d2); 01402 cob_decimal_init (&cob_d3); 01403 cob_decimal_init (&cob_d4); 01404 mpz_init2 (cob_mpzt, 256); 01405 mpz_init2 (cob_mexp, 512); 01406 for (i = 0; i < COB_MAX_BINARY; i++) { 01407 mpz_init (cob_mpze10[i]); 01408 mpz_ui_pow_ui (cob_mpze10[i], 10, i); 01409 } 01410 num_buff_ptr = cob_malloc (2048); 01411 memset (packed_value, 0, sizeof(packed_value)); 01412 } 01413 01414 /* Numeric Display compares */ 01415 01416 int 01417 cob_cmp_numdisp (const unsigned char *data, const size_t size, const int n) 01418 { 01419 const unsigned char *p; 01420 size_t inc; 01421 int val = 0; 01422 01423 p = data; 01424 for (inc = 0; inc < size; inc++, p++) { 01425 val = (val * 10) + (*p - (unsigned char)'0'); 01426 } 01427 return (val < n) ? -1 : (val > n); 01428 } 01429 01430 int 01431 cob_cmp_long_numdisp (const unsigned char *data, const size_t size, const int n) 01432 { 01433 const unsigned char *p; 01434 long long val = 0; 01435 size_t inc; 01436 01437 p = data; 01438 for (inc = 0; inc < size; inc++, p++) { 01439 val = (val * 10) + (*p - (unsigned char)'0'); 01440 } 01441 return (val < n) ? -1 : (val > n); 01442 } 01443 01444 #ifdef COB_EBCDIC_MACHINE 01445 static void 01446 cob_get_ascii_sign (const unsigned char *p, int *val) 01447 { 01448 switch (*p) { 01449 case 'p': 01450 return; 01451 case 'q': 01452 *val += 1; 01453 return; 01454 case 'r': 01455 *val += 2; 01456 return; 01457 case 's': 01458 *val += 3; 01459 return; 01460 case 't': 01461 *val += 4; 01462 return; 01463 case 'u': 01464 *val += 5; 01465 return; 01466 case 'v': 01467 *val += 6; 01468 return; 01469 case 'w': 01470 *val += 7; 01471 return; 01472 case 'x': 01473 *val += 8; 01474 return; 01475 case 'y': 01476 *val += 9; 01477 return; 01478 } 01479 } 01480 01481 static void 01482 cob_get_long_ascii_sign (const unsigned char *p, long long *val) 01483 { 01484 switch (*p) { 01485 case 'p': 01486 return; 01487 case 'q': 01488 *val += 1; 01489 return; 01490 case 'r': 01491 *val += 2; 01492 return; 01493 case 's': 01494 *val += 3; 01495 return; 01496 case 't': 01497 *val += 4; 01498 return; 01499 case 'u': 01500 *val += 5; 01501 return; 01502 case 'v': 01503 *val += 6; 01504 return; 01505 case 'w': 01506 *val += 7; 01507 return; 01508 case 'x': 01509 *val += 8; 01510 return; 01511 case 'y': 01512 *val += 9; 01513 return; 01514 } 01515 } 01516 #endif 01517 01518 static int 01519 cob_get_ebcdic_sign (const unsigned char *p, int *val) 01520 { 01521 switch (*p) { 01522 case '{': 01523 return 0; 01524 case 'A': 01525 *val += 1; 01526 return 0; 01527 case 'B': 01528 *val += 2; 01529 return 0; 01530 case 'C': 01531 *val += 3; 01532 return 0; 01533 case 'D': 01534 *val += 4; 01535 return 0; 01536 case 'E': 01537 *val += 5; 01538 return 0; 01539 case 'F': 01540 *val += 6; 01541 return 0; 01542 case 'G': 01543 *val += 7; 01544 return 0; 01545 case 'H': 01546 *val += 8; 01547 return 0; 01548 case 'I': 01549 *val += 9; 01550 return 0; 01551 case '}': 01552 return 1; 01553 case 'J': 01554 *val += 1; 01555 return 1; 01556 case 'K': 01557 *val += 2; 01558 return 1; 01559 case 'L': 01560 *val += 3; 01561 return 1; 01562 case 'M': 01563 *val += 4; 01564 return 1; 01565 case 'N': 01566 *val += 5; 01567 return 1; 01568 case 'O': 01569 *val += 6; 01570 return 1; 01571 case 'P': 01572 *val += 7; 01573 return 1; 01574 case 'Q': 01575 *val += 8; 01576 return 1; 01577 case 'R': 01578 *val += 9; 01579 return 1; 01580 } 01581 return 0; 01582 } 01583 01584 static int 01585 cob_get_long_ebcdic_sign (const unsigned char *p, long long *val) 01586 { 01587 switch (*p) { 01588 case '{': 01589 return 0; 01590 case 'A': 01591 *val += 1; 01592 return 0; 01593 case 'B': 01594 *val += 2; 01595 return 0; 01596 case 'C': 01597 *val += 3; 01598 return 0; 01599 case 'D': 01600 *val += 4; 01601 return 0; 01602 case 'E': 01603 *val += 5; 01604 return 0; 01605 case 'F': 01606 *val += 6; 01607 return 0; 01608 case 'G': 01609 *val += 7; 01610 return 0; 01611 case 'H': 01612 *val += 8; 01613 return 0; 01614 case 'I': 01615 *val += 9; 01616 return 0; 01617 case '}': 01618 return 1; 01619 case 'J': 01620 *val += 1; 01621 return 1; 01622 case 'K': 01623 *val += 2; 01624 return 1; 01625 case 'L': 01626 *val += 3; 01627 return 1; 01628 case 'M': 01629 *val += 4; 01630 return 1; 01631 case 'N': 01632 *val += 5; 01633 return 1; 01634 case 'O': 01635 *val += 6; 01636 return 1; 01637 case 'P': 01638 *val += 7; 01639 return 1; 01640 case 'Q': 01641 *val += 8; 01642 return 1; 01643 case 'R': 01644 *val += 9; 01645 return 1; 01646 } 01647 return 0; 01648 } 01649 01650 int 01651 cob_cmp_sign_numdisp (const unsigned char *data, const size_t size, const int n) 01652 { 01653 const unsigned char *p; 01654 int val = 0; 01655 size_t inc; 01656 01657 p = data; 01658 for (inc = 0; inc < size - 1; inc++, p++) { 01659 val = (val * 10) + (*p - (unsigned char)'0'); 01660 } 01661 val *= 10; 01662 if (*p >= '0' && *p <= '9') { 01663 val += (*p - (unsigned char)'0'); 01664 } else { 01665 if (unlikely(cob_current_module->display_sign)) { 01666 if (cob_get_ebcdic_sign (p, &val)) { 01667 val = -val; 01668 } 01669 } else { 01670 #ifdef COB_EBCDIC_MACHINE 01671 cob_get_ascii_sign (p, &val); 01672 #else 01673 val += (*p - (unsigned char)'p'); 01674 #endif 01675 val = -val; 01676 } 01677 } 01678 return (val < n) ? -1 : (val > n); 01679 } 01680 01681 int 01682 cob_cmp_long_sign_numdisp (const unsigned char *data, const size_t size, const int n) 01683 { 01684 const unsigned char *p; 01685 long long val = 0; 01686 size_t inc; 01687 01688 p = data; 01689 for (inc = 0; inc < size - 1; inc++, p++) { 01690 val = (val * 10) + (*p - (unsigned char)'0'); 01691 } 01692 val *= 10; 01693 if (*p >= '0' && *p <= '9') { 01694 val += (*p - (unsigned char)'0'); 01695 } else { 01696 if (unlikely(cob_current_module->display_sign)) { 01697 if (cob_get_long_ebcdic_sign (p, &val)) { 01698 val = -val; 01699 } 01700 } else { 01701 #ifdef COB_EBCDIC_MACHINE 01702 cob_get_long_ascii_sign (p, &val); 01703 #else 01704 val += (*p - (unsigned char)'p'); 01705 #endif 01706 val = -val; 01707 } 01708 } 01709 return (val < n) ? -1 : (val > n); 01710 }