1386 lines
43 KiB
C
1386 lines
43 KiB
C
/*
|
|
* Copyright (C) 2001, 2000, 1999, Rildo Pragana, Jim Noeth,
|
|
* Andrew Cameron, David Essex.
|
|
* Copyright (C) 1993, 1991 Rildo Pragana.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1,
|
|
* or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; see the file COPYING.LIB. If
|
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place,
|
|
* Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* COBOL Compiler Run Time Library -- Math Module
|
|
*
|
|
*/
|
|
|
|
#include "htcoblib.h"
|
|
|
|
#include <math.h>
|
|
|
|
/* undef DEBUG_RTS */
|
|
/* define DEBUG_RTS 1 */
|
|
/* define DEBUG_MOVE_RTS 1 */
|
|
|
|
#if defined DEBUG_RTS
|
|
/* #define DEBUG_RTN(fmt, p1, p2, p3, p4, p5, p6)
|
|
{fprintf(stderr, fmt, p1, p2, p3, p4, p5, p6);} */
|
|
#else
|
|
/* #define DEBUG_RTN(fmt, p1, p2, p3, p4, p5, p6) */
|
|
#endif
|
|
|
|
/* global data */
|
|
static double exp10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13,
|
|
1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25,
|
|
1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37,
|
|
1e38, 1e39, 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
|
|
1e50};
|
|
|
|
struct fld_desc _generic_4binary = {4, DTYPE_BININT, 0, 0, 0, 0, 0, 0, 0, 0, "S\19\x09"};
|
|
|
|
struct fld_desc _generic_8float = {8, DTYPE_FLOAT, 15, 0, 0, 0, 0, 0, 0, 0, "S\19\x0fV\19\x0f"};
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| fp_runtime_error |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
#if 0
|
|
|
|
static void
|
|
fp_runtime_error(struct fld_desc *f)
|
|
{
|
|
char *pic;
|
|
fprintf(stderr, "math runtime error: *** invalid contents of numeric field ***\n");
|
|
pic = tcob_picExpand(f);
|
|
fprintf(stderr, "field len: %ld, type: %c, decimals: %d, pic: %s\n",
|
|
f->len, f->type, f->decimals, pic);
|
|
free(pic);
|
|
/* getchar();*/
|
|
}
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| dump_double |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
#if 0
|
|
|
|
static void
|
|
dump_double(char *msg, unsigned char *ptr)
|
|
{
|
|
int i;
|
|
printf(msg);
|
|
for (i = 7; i >= 0; i--)
|
|
printf("%02.2x", ptr[i]);
|
|
getchar();
|
|
}
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_sign_to_char |
|
|
| input: digit (-9..-1,0,1..9, or 0x80 for -0) |
|
|
| return: character +0...+9:"{ABCDEFGHI" -0...-9:"}JKLMNOPQR" |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
char
|
|
tcob_sign_to_char(int digit)
|
|
{
|
|
if (!digit)
|
|
return '{';
|
|
|
|
if (digit == 0x80)
|
|
return '}';
|
|
|
|
if (digit > 0)
|
|
return 'A' + (char) (digit - 1);
|
|
|
|
digit = -digit;
|
|
|
|
return 'J' + (char) (digit - 1);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_char_to_sign |
|
|
| input and return are reverse those of tcob_sign_to_char |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_char_to_sign(char ch)
|
|
{
|
|
if (ch == '{')
|
|
return 0;
|
|
|
|
if (ch == '}')
|
|
return 0x80;
|
|
|
|
if (ch < 'J')
|
|
return (int) (ch - 'A' + 1);
|
|
|
|
return (-(int) (ch - 'J' + 1));
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_extract_sign |
|
|
| return: sign (0 is +, 1 is -) |
|
|
| modified: s[f->len-1] (if type is not PACKED and is signed) |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
char
|
|
tcob_extract_sign(struct fld_desc *f, char *s)
|
|
{
|
|
char *tmp;
|
|
int digit;
|
|
|
|
if (tcob_picElemVal(f->pic, 0) != 'S')
|
|
return 0;
|
|
|
|
if (f->type == DTYPE_PACKED)
|
|
{
|
|
digit = s[f->len / 2] & 0x0F;
|
|
return (((digit == 0x0D) || (digit == 0x0B)) ? 1 : 0);
|
|
}
|
|
|
|
tmp = (f->leading_sign) ? s : s + f->len - 1;
|
|
digit = tcob_char_to_sign(*tmp);
|
|
|
|
if (digit == 0x80)
|
|
*tmp = '0';
|
|
else
|
|
if (digit < 0)
|
|
*tmp = '0' - digit;
|
|
else
|
|
{
|
|
*tmp = '0' + digit;
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_put_sign |
|
|
| modified: possibly s[f->len/2] or s[f->len-1] |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void
|
|
tcob_put_sign(struct fld_desc *f, char *s, char sign)
|
|
{
|
|
char *tmp;
|
|
int digit;
|
|
|
|
if (f->type == DTYPE_PACKED)
|
|
{
|
|
if (tcob_picElemVal(f->pic, 0) == 'S')
|
|
digit = (sign) ? 0x0D : 0x0C;
|
|
else
|
|
digit = 0x0F;
|
|
|
|
s[f->len / 2] = (s[f->len / 2] & 0xF0) | digit;
|
|
return;
|
|
}
|
|
if (tcob_picElemVal(f->pic, 0) != 'S')
|
|
return;
|
|
|
|
tmp = (f->leading_sign) ? s : s + f->len - 1;
|
|
digit = *tmp - '0';
|
|
/* fprintf(stderr, "tcob_put_sign: t=%c,d=%d,s=%d\n",*tmp,digit,sign); */
|
|
if (sign)
|
|
digit = -digit;
|
|
|
|
*tmp = tcob_sign_to_char((sign && digit == 0) ? 0x80 : digit);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_adjust_length |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
struct fld_desc *
|
|
tcob_adjust_length(struct fld_desc *dep_desc, char *dep_val, int min, int max,
|
|
struct fld_desc *var_desc, struct fld_desc *item, struct fld_desc *copy)
|
|
{
|
|
int itocc;
|
|
tcob_move(dep_desc, dep_val, &_generic_4binary, (char *) & itocc);
|
|
if (itocc < min || itocc > max)
|
|
{
|
|
/* should generate exception, for now just a warning */
|
|
fprintf(stderr, "*** Warning: table size out of bounds ");
|
|
fprintf(stderr, "(requested = %d, min = %d, max = %d)\n", itocc, min,
|
|
max);
|
|
itocc = max;
|
|
}
|
|
|
|
memmove(copy, var_desc, sizeof (struct fld_desc));
|
|
copy->len -= (max - itocc) * item->len;
|
|
return copy;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_get_index & al. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_get_index(struct fld_desc *f, char *s)
|
|
{
|
|
int index;
|
|
|
|
tcob_move(f, s, &_generic_4binary, (char *) & index);
|
|
return index;
|
|
}
|
|
|
|
int
|
|
tcob_cnv_ll2i(long long idx)
|
|
{
|
|
/* If a run-time truncation check should occur, it should be here */
|
|
return (int) idx;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_fldtod |
|
|
| Convert from a string to a double based on the fld_desc |
|
|
| modified: *fp |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void
|
|
tcob_fldtod(struct fld_desc *f, char *s, double *fp)
|
|
{
|
|
unsigned int i;
|
|
unsigned char sign = 0;
|
|
unsigned char fpdig;
|
|
int scale;
|
|
double fpp = 0.;
|
|
|
|
#ifdef DEBUG_MOVE_RTS
|
|
fprintf(stderr, "debug: tcob_fldtod 1: f: type=%c, len=%ld, dec=%d, s=%s\n",
|
|
f->type,
|
|
f->len,
|
|
f->decimals,
|
|
s);
|
|
#endif
|
|
|
|
switch (f->type)
|
|
{
|
|
case DTYPE_BININT:
|
|
switch (f->len)
|
|
{
|
|
case 1:
|
|
fpp = (double) *((char *) s);
|
|
break;
|
|
case 2:
|
|
fpp = (double) *((short int *) s);
|
|
break;
|
|
case 4:
|
|
fpp = (double) *((int *) s);
|
|
break;
|
|
case 8:
|
|
fpp = (double) *((long long *) s);
|
|
break;
|
|
}
|
|
/* fprintf(stderr, "debug: tcob_fldtod 3: f->len=%d, fpp=%f, s=%d\n",
|
|
f->len,
|
|
fpp,
|
|
*((int *)s)); */
|
|
break;
|
|
case DTYPE_PACKED:
|
|
for (i = 0;; i++)
|
|
{
|
|
fpdig = ((i & 1) ? s[i / 2] : s[i / 2] >> 4) & 0x0F;
|
|
if (fpdig > 9)
|
|
break;
|
|
fpp *= 10.;
|
|
fpp += (double) fpdig;
|
|
}
|
|
sign = ((fpdig == 0x0D) || (fpdig == 0x0B)) ? 1 : 0;
|
|
break;
|
|
case DTYPE_FLOAT:
|
|
switch (f->len)
|
|
{
|
|
case 4:
|
|
fpp = (double) *((float *) s);
|
|
/* fprintf(stderr, "debug: tcob_fldtod 3a: fpp=%f, s=%f\n",
|
|
fpp, *((float *)s)); */
|
|
break;
|
|
case 8:
|
|
fpp = (double) *((double *) s);
|
|
/* fprintf(stderr, "debug: tcob_fldtod 3b: fpp=%f, s=%f\n",
|
|
fpp, *((double *)s)); */
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
if (f->separate_sign)
|
|
{
|
|
f->len--;
|
|
if (f->leading_sign)
|
|
{
|
|
sign = (s[0] == '-') ? 1 : 0;
|
|
s++;
|
|
}
|
|
else
|
|
sign = (s[f->len] == '-') ? 1 : 0;
|
|
}
|
|
else
|
|
sign = tcob_extract_sign(f, s);
|
|
for (i = 0; i < f->len; i++)
|
|
{
|
|
fpdig = (s[i] == ' ') ? 0 : s[i] - '0';
|
|
fpp *= 10.;
|
|
fpp += (double) fpdig;
|
|
}
|
|
if (f->separate_sign)
|
|
{
|
|
f->len++;
|
|
if (f->leading_sign)
|
|
s--;
|
|
}
|
|
else
|
|
tcob_put_sign(f, s, sign);
|
|
break;
|
|
}
|
|
|
|
/* scale the number with it's (fld_desc *)->decimals */
|
|
/* No decimal scaling required for floating types */
|
|
if (f->type != DTYPE_FLOAT)
|
|
{
|
|
scale = f->decimals;
|
|
if (scale == 0 && f->pscale < 0)
|
|
scale = f->pscale;
|
|
/* fprintf(stderr, "debug: tcob_fldtod 8a: scale=%d\n", scale); */
|
|
if (scale > 0 && scale <= 50)
|
|
fpp /= exp10[scale];
|
|
else if (scale > 50) /* because our table don't have everything */
|
|
fpp /= pow(10., (double) scale);
|
|
else if (scale < 0) /* because our table don't have everything */
|
|
fpp /= pow(10., (double) scale);
|
|
if (sign)
|
|
fpp = -fpp;
|
|
/*dump_double( "\fRes:",&fpp );*/
|
|
|
|
}
|
|
|
|
*fp = fpp;
|
|
|
|
#ifdef DEBUG_MOVE_RTS
|
|
fprintf(stderr, "debug: tcob_fldtod 9: f: type=%c, len=%d, dec=%d; fpp=%g\n",
|
|
f->type, (int) f->len, f->decimals, fpp);
|
|
#endif
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_push_double |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void
|
|
tcob_push_double(struct fld_desc *f, char *s, double d)
|
|
{
|
|
tcob_fldtod(f, s, &d);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| do_rounding |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
do_rounding(struct fld_desc *f, double *d1)
|
|
{
|
|
double fp = *d1;
|
|
double rounding_incr = .5;
|
|
|
|
/* fp *= exp10[f->decimals]; */
|
|
if (fp < 0)
|
|
{
|
|
rounding_incr = -rounding_incr;
|
|
}
|
|
if (f->pscale < 0)
|
|
rounding_incr *= exp10[-(f->pscale)];
|
|
else
|
|
rounding_incr /= exp10[f->decimals];
|
|
/* fprintf(stderr, "debug: do_rounding 1: d1=%f, dec=%d, ri=%f\n",
|
|
fp, f->decimals, rounding_incr); */
|
|
fp += rounding_incr;
|
|
/* fprintf(stderr, "debug: do_rounding 2: d1=%f\n", fp); */
|
|
*d1 = fp;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_assign_double |
|
|
| opts: bit 0 = ROUNDED |
|
|
| bit 1 = ON SIZE ERROR |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_assign_double(struct fld_desc *f, char *s1, int opts, double d1)
|
|
{
|
|
int rc = 0;
|
|
int rc1 = 0;
|
|
double tempd = d1; /* do not change d1, as it only exists on the stack */
|
|
|
|
#ifdef DEBUG_MOVE_RTS
|
|
fprintf(stderr, "debug: tcob_assign_double 1: d1=%f\n", d1);
|
|
#endif
|
|
if (f->type == DTYPE_EDITED)
|
|
f->decimals = tcob_picEditedCompDecimals(f);
|
|
|
|
/* <--- WE MUST ROUND EVER, AS WE ARE DOING
|
|
FLOATING POINT OPERATIONS. tHE REAL FIX
|
|
IS TO CHANGE MATH IN THE COMPILER.
|
|
PLEASE, DO NOT REMOVE "do_rounding". */
|
|
if (opts & 1)
|
|
do_rounding(f, &tempd);
|
|
|
|
// Always checks on size error, even the user program do not test that...
|
|
// if (opts & 2)
|
|
rc = tcob_check_size_overflow(f, tempd);
|
|
|
|
#ifdef DEBUG_MOVE_RTS
|
|
fprintf(stderr, "debug: tcob_assign_double 2: d1=%f, s1=%s, rc=%d\n", d1, s1, rc);
|
|
#endif
|
|
|
|
// TODO: Always move????
|
|
//if (rc == 0)
|
|
rc1 = tcob_dtofld(f, s1, 0, tempd); /* no rounding, already done */
|
|
/* tcob_move( &_generic_8float, (char *)&tempd, f, s1 ); */
|
|
|
|
#ifdef DEBUG_MOVE_RTS
|
|
fprintf(stderr, "debug: tcob_assign_double 3: d1=%f, s1=%s, rc=%d\n", d1, s1, rc);
|
|
|
|
if (rc != 0)
|
|
fprintf(stderr, "debug: size error on field of type %c\n", f->type);
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_dtofld |
|
|
| Convert from a double to a string based on the fld_desc, |
|
|
| rounding if indicated by round |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_dtofld(struct fld_desc *f, char *s1, int round, double d1)
|
|
{
|
|
int ndec;
|
|
unsigned int i, len, nd;
|
|
unsigned int sign, rc = 0;
|
|
//unsigned int lenDest;
|
|
//double remainder; walter
|
|
double fpa;
|
|
char form[10];
|
|
char saida[128];
|
|
|
|
memset(&saida[0], 0, 128);
|
|
memset(&form[0], 0, 10);
|
|
form[0] = '%';
|
|
form[1] = '0';
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld 0: d1=%f, rc=%d\n", d1, rc);
|
|
#endif
|
|
|
|
switch (f->type)
|
|
{
|
|
case DTYPE_BININT:
|
|
d1 *= exp10[f->decimals];
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld 2a: d1=%f, rc=%d\n", d1, rc);
|
|
#endif
|
|
|
|
if (round != 0)
|
|
d1 += (d1 > 0.) ? .5 : -.5;
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld 2b: d1=%f, rc=%d\n", d1, rc);
|
|
#endif
|
|
|
|
switch (f->len)
|
|
{
|
|
case 1:
|
|
*((char *) s1) = (int) d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 2-1: d1=%f, s1=%d\n",
|
|
d1, *((char *)s1)); */
|
|
break;
|
|
case 2:
|
|
*((short int *) s1) = (int) d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 2-2: d1=%f, s1=%d\n",
|
|
d1, *((short int *)s1)); */
|
|
break;
|
|
case 4:
|
|
*((int *) s1) = (int) d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 2-4: d1=%f, s1=%d, fi=%d\n",
|
|
d1, *((int *)s1), fi); */
|
|
break;
|
|
case 8:
|
|
*((long long *) s1) = (long long) d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 2-8: d1=%f, s1=%d\n",
|
|
d1, *((long long *)s1)); */
|
|
break;
|
|
}
|
|
return rc;
|
|
case DTYPE_PACKED:
|
|
len = f->len;
|
|
break;
|
|
case DTYPE_FLOAT:
|
|
switch (f->len)
|
|
{
|
|
case 4:
|
|
*((float *) s1) = (float) d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 3: d1=%f, s1=%f\n",
|
|
d1, *((float *)s1)); */
|
|
break;
|
|
case 8:
|
|
*((double *) s1) = d1;
|
|
/* fprintf(stderr, "debug: tcob_dtofld 4: d1=%f, s1=%f\n",
|
|
d1, *((double *)s1)); */
|
|
break;
|
|
default:
|
|
rc = 1;
|
|
break;
|
|
}
|
|
/* fprintf(stderr, "debug: tcob_dtofld 5: d1=%f, rc=%d\n",
|
|
d1, rc); */
|
|
return rc;
|
|
case DTYPE_EDITED:
|
|
len = tcob_picEditedCompLength(f);
|
|
break;
|
|
default:
|
|
len = f->len;
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld default: LEN=%d d1=%f\n", len, d1);
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
/*dump_double("\fAssign: ",&d1);*/
|
|
fpa = d1;
|
|
if (f->type == DTYPE_EDITED)
|
|
ndec = tcob_picEditedCompDecimals(f);
|
|
else
|
|
ndec = (int) f->decimals;
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld 6: fpa=%f,dec=%d,len=%d\n", fpa, ndec, (int) f->len);
|
|
#endif
|
|
|
|
if (fpa < 0.)
|
|
{
|
|
sign = 1;
|
|
fpa = -fpa;
|
|
}
|
|
else
|
|
sign = 0;
|
|
|
|
nd = len + ndec;
|
|
if (ndec > 0)
|
|
nd += (f->separate_sign ? 0 : 1);
|
|
if (ndec) // walter
|
|
sprintf(&form[2], "%i.%if", nd, ndec);
|
|
else
|
|
sprintf(&form[2], "%i.1f", (nd + 2));
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld 6a: len=%d, ndec=%d, exp10[len-ndec]=%f, fpa=%f\n",
|
|
len, ndec, exp10[len - ndec], fpa);
|
|
#endif
|
|
|
|
#if 0
|
|
/* Do not remove this code */
|
|
if (fpa > exp10[len - ndec])
|
|
{
|
|
fp_runtime_error(f);
|
|
rc = 1;
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
fpa *= exp10[ndec];
|
|
// remainder = fpa - (unsigned long) fpa;
|
|
// if (f->pscale < 0) {
|
|
// fpa /= exp10[abs(f->pscale)];
|
|
// remainder /= exp10[abs(f->pscale)];
|
|
// }
|
|
|
|
/* the following line is to fix a truncation error caused by rounding
|
|
* in converting from long to double to long (i.e. 4.5 to 4.49999...).
|
|
*/
|
|
/* fprintf(stderr, "debug: tcob_dtofld 6: fpa=%f, round=%d\n", fpa,round); */
|
|
// if (remainder >= 0.999999) // walter tinha 0.9999999
|
|
// fpa += 0.000001; // tinha 0.0000001
|
|
/* if ( (round != 0) || ((unsigned long)(fpa * 10) % 10 > 8) )
|
|
fpa += (fpa > 0.) ? .5 : -.5; */
|
|
/* fprintf(stderr, "debug: tcob_dtofld 7: fpa=%f\n", fpa); */
|
|
/* if (fpa>pow(2.,32.)) {
|
|
printf("\fFP overflow!"); getchar();
|
|
return;
|
|
}
|
|
*/
|
|
|
|
if (f->type != DTYPE_PACKED)
|
|
{
|
|
//unsigned int mini; walter
|
|
//unsigned long fint; walter
|
|
char *s;
|
|
if (f->type == DTYPE_EDITED)
|
|
s = (char *) malloc(len);
|
|
else
|
|
s = s1;
|
|
|
|
/* if separate sign, tack on and hide */
|
|
if (f->separate_sign)
|
|
{
|
|
char cSign = (sign) ? '-' : '+';
|
|
if (f->leading_sign)
|
|
{
|
|
s[0] = cSign;
|
|
s++;
|
|
}
|
|
else
|
|
s[len - 1] = cSign;
|
|
len--;
|
|
}
|
|
|
|
memset(s, '0', len); // TODO: What???? See the IF above...
|
|
|
|
// put on "s" just the rightmost picture size characters
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld: ANTES: len=%d, dec=%d\n", f->len, f->decimals);
|
|
fprintf(stderr, "debug: tcob_dtofld: ANTES: value=[%f], saida=[%s], s=[%s]\n", fpa, saida, s);
|
|
#endif
|
|
|
|
char *ss;
|
|
ss = (char *) malloc(f->len + 2); // size plus 2... sign and terminator
|
|
memset(ss,0,f->len+2);
|
|
|
|
// put value on "saida"
|
|
sprintf(&saida[0], &form[0], fpa); //walter
|
|
|
|
// saida has something like 2400099.00 for 24000,99 and PIC 9(4)V9(2)
|
|
i = 0;
|
|
while (saida[i] && saida[i] != '.')
|
|
{
|
|
ss[i] = saida[i];
|
|
i++;
|
|
}
|
|
|
|
// we must transfer from ss to s, limited to the size of the picture (on the sample, 6)
|
|
|
|
// if value less or equal than picture size, just copy it to output
|
|
// otherwise, limits the copy to size defined by the picture
|
|
if (strlen(ss) <= f->len)
|
|
strcpy(s, ss);
|
|
else
|
|
{
|
|
i = strlen(ss) - f->len;
|
|
memcpy(s, &ss[i], f->len);
|
|
}
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_dtofld: DEPOIS: len=%d, dec=%d\n", f->len, f->decimals);
|
|
fprintf(stderr, "debug: tcob_dtofld: DEPOIS: value=[%f], saida=[%s], s=[%s], ss=[%s]\n", fpa, saida, s, ss);
|
|
#endif
|
|
|
|
// for numeric edited, move value and clean up
|
|
if (f->type == DTYPE_EDITED)
|
|
{
|
|
struct fld_desc fcopy;
|
|
unsigned int picLen = tcob_picReqLen(4);
|
|
memcpy(&fcopy, f, sizeof (struct fld_desc));
|
|
fcopy.pic = (char *) malloc(picLen);
|
|
tcob_picCreate(fcopy.pic, picLen, 'S', 1, '9', len - ndec, NULL);
|
|
if (ndec > 0)
|
|
tcob_picAppend(fcopy.pic, picLen, 'V', 1, '9', ndec, NULL);
|
|
fcopy.type = DTYPE_DISPLAY;
|
|
fcopy.len = len;
|
|
fcopy.decimals = ndec;
|
|
tcob_put_sign(&fcopy, s, sign);
|
|
tcob_move(&fcopy, s, f, s1);
|
|
free(fcopy.pic);
|
|
free(s);
|
|
}
|
|
|
|
/* tack on the sign */
|
|
if (!(f->separate_sign))
|
|
tcob_put_sign(f, s1, sign);
|
|
}
|
|
|
|
// fprintf(stderr, "\nString: %20.20s\n", s);
|
|
// getchar();
|
|
|
|
if (f->type == DTYPE_PACKED)
|
|
{
|
|
unsigned long long fpahold = (unsigned long long) fpa;
|
|
unsigned char cDigit, cSign;
|
|
|
|
memset(s1, 0, (len / 2) + 1); /* Initialize s1 array */
|
|
|
|
if ((len & 1) == 0) /* Make sure length is odd */
|
|
len++;
|
|
|
|
/* convert scaled number in fpa to our result */
|
|
for (i = len; (i > 0) && (fpahold != 0); i--)
|
|
{
|
|
cDigit = fpahold % 10;
|
|
if ((i % 2) == 1)
|
|
cDigit <<= 4;
|
|
fpahold /= 10;
|
|
s1[(i - 1) / 2] |= cDigit;
|
|
}
|
|
|
|
/* attach the sign */
|
|
if (tcob_picElemVal(f->pic, 0) == 'S')
|
|
cSign = (sign) ? 0x0D : 0x0C;
|
|
else
|
|
cSign = 0x0F;
|
|
s1[len / 2] |= cSign;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_add_double |
|
|
| tcob_subtract_double |
|
|
| tcob_multiply_double |
|
|
| tcob_divide_double |
|
|
| tcob_pow_double |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void
|
|
tcob_add_double(double *d2, double d1)
|
|
{
|
|
*d2 += d1;
|
|
}
|
|
|
|
void
|
|
tcob_subtract_double(double *d2, double d1)
|
|
{
|
|
*d2 -= d1;
|
|
}
|
|
|
|
void
|
|
tcob_multiply_double(double *d2, double d1)
|
|
{
|
|
*d2 *= d1;
|
|
|
|
// due to a bug on gcc...
|
|
if (*d2 == 0)
|
|
*d2 = 0;
|
|
}
|
|
|
|
void
|
|
tcob_divide_double(double *d2, double d1)
|
|
{
|
|
#if 0
|
|
/* check for divide by zero */
|
|
if (d1 == 0)
|
|
{
|
|
fprintf(stderr, "*** RUNTIME ERROR: divide by zero\n");
|
|
exit(1);
|
|
}
|
|
#endif
|
|
if (d1 == 0)
|
|
*d2 = 0;
|
|
else
|
|
*d2 /= d1;
|
|
}
|
|
|
|
void
|
|
tcob_pow_double(double *d2, double d1)
|
|
{
|
|
*d2 = pow(*d2, d1);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_add |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_add(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2, int round)
|
|
{
|
|
int rc = 0;
|
|
double fp1, fp2;
|
|
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
fp1 += fp2;
|
|
rc = tcob_check_size_overflow(f2, fp1);
|
|
if (rc == 0)
|
|
tcob_dtofld(f2, s2, round, fp1);
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_subtract |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_subtract(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2, int round)
|
|
{
|
|
int rc = 0;
|
|
double fp1, fp2;
|
|
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
fp2 -= fp1;
|
|
rc = tcob_check_size_overflow(f2, fp2);
|
|
if (rc == 0)
|
|
tcob_dtofld(f2, s2, round, fp2);
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_multiply |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_multiply(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2, struct fld_desc *f3, char *s3, int round)
|
|
{
|
|
int rc = 0;
|
|
double fp1, fp2, fp3;
|
|
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
fp3 = fp1 * fp2;
|
|
rc = tcob_check_size_overflow(f3, fp3);
|
|
if (rc == 0)
|
|
tcob_dtofld(f3, s3, round, fp3);
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_divide |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_divide(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2,
|
|
struct fld_desc *f3, char *s3, int round)
|
|
{
|
|
int rc = 0;
|
|
double fp1, fp2, fp3;
|
|
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
if (fp2 == 0)
|
|
rc = 1;
|
|
else
|
|
{
|
|
fp3 = fp1 / fp2;
|
|
rc = tcob_check_size_overflow(f3, fp3);
|
|
if (rc == 0)
|
|
tcob_dtofld(f3, s3, round, fp3);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_divide1 |
|
|
| Divide with remainder option |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_divide1(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2,
|
|
struct fld_desc *f3, char *s3, struct fld_desc *f4, char *s4, int round)
|
|
{
|
|
int rc = 0;
|
|
double fp1, fp2, fp3, fp4, tfp3;
|
|
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
/* fprintf(stderr, "debug mcmath 1: fp1=%05.5f fp2=%05.5f\n", fp1, fp2); */
|
|
if (fp2 == 0)
|
|
{ /* divide by zero error */
|
|
rc = 1;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Calculate GIVING
|
|
*/
|
|
fp3 = fp1 / fp2;
|
|
/* fprintf(stderr, "debug mcmath 2: fp3=%05.5f\n", fp3); */
|
|
rc = tcob_check_size_overflow(f3, fp3);
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
tcob_dtofld(f3, s3, round, fp3);
|
|
|
|
/*
|
|
* Calculate REMAINDER.
|
|
*/
|
|
|
|
tcob_fldtod(f3, s3, &tfp3);
|
|
|
|
fp4 = (fp1 - (tfp3 * fp2));
|
|
/* fprintf(stderr, "debug mcmath 3: fp4=%05.5f, tfp3=%05.5f\n", fp4, tfp3); */
|
|
rc = tcob_check_size_overflow(f4, fp4);
|
|
if (rc != 0)
|
|
{
|
|
/* fprintf(stderr, "debug mcmath 4: check_size_overflow : "
|
|
"a overflow has occured on fp4=%05.5f\n",
|
|
fp4); */
|
|
return rc;
|
|
}
|
|
|
|
/* fprintf(stderr, "debug mcmath 4: fp1=%05.5f, fp2=%05.5f, fp3=%05.5f, tfp3=%05.5f, fp4=%05.5f, fp4=%05.5f\n", fp1, fp2, fp3, tfp3, fp4, fp4); */
|
|
tcob_dtofld(f4, s4, 0, fp4);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_size_overflow |
|
|
| Check if size will fit in destination field. 0 if yes, 1 if false. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_size_overflow(struct fld_desc *f, double d)
|
|
{
|
|
unsigned int rc, len;
|
|
|
|
if (f->type == DTYPE_EDITED)
|
|
len = tcob_picEditedCompLength(f);
|
|
else
|
|
len = tcob_picCompLength(f) + tc_abs((char) f->pscale);
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_check_size_overflow 1: piclen=%d, f->len=%d, f->decimals=%d\n",
|
|
len, (int) f->len, f->decimals);
|
|
#endif
|
|
if (len < f->decimals)
|
|
{
|
|
rc = 1;
|
|
}
|
|
else if (((d < 0.0) ? -d : d) >= exp10[len - f->decimals])
|
|
{
|
|
rc = 1;
|
|
}
|
|
else
|
|
{
|
|
rc = 0;
|
|
}
|
|
|
|
#ifdef DEBUG_RTS
|
|
fprintf(stderr, "debug: tcob_check_size_overflow 2: d=%g, rc=%d\n",
|
|
d, rc);
|
|
#endif
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_numeric |
|
|
| test if all data in variable conforms to its class (type) |
|
|
| 0 if true, 1 if false. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_numeric(struct fld_desc *f, char *s)
|
|
{
|
|
unsigned int i, dig = 0;
|
|
char c;
|
|
|
|
if ((f->type == DTYPE_BININT) || (f->type == DTYPE_PACKED) || (f->type
|
|
== DTYPE_FLOAT))
|
|
return 0; /* these types are assumed to always be valid */
|
|
for (i = 0; i < f->len; i++)
|
|
{
|
|
c = s[i];
|
|
/* must have at least one digit */
|
|
if (!dig && (c >= '0') && (c <= '9'))
|
|
dig++;
|
|
if (i == 0 && ((c == ' ') || (c == '+') || (c == '-')))
|
|
continue;
|
|
/* look for a number followed by several spaces (is this valid?) */
|
|
if (c == ' ')
|
|
{
|
|
for (; i < f->len; i++)
|
|
{
|
|
if (s[i] != ' ')
|
|
return 1;
|
|
}
|
|
break;
|
|
}
|
|
/*
|
|
Omit: NULL picture (bug in refmod's)
|
|
No picture in group items
|
|
*/
|
|
if ((f->pic != NULL) && (f->type != DTYPE_GROUP))
|
|
{
|
|
/* take care of signed numbers (non separate sign) */
|
|
if ((i == f->len - 1) && (tcob_picElemVal(f->pic, 0) == 'S'))
|
|
{
|
|
if (strchr("}ABCDEFGHI{JKLMNOPQR", c) != NULL)
|
|
{
|
|
dig++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ((c > '9') || (c < '0'))
|
|
return 1;
|
|
}
|
|
if (!dig)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_alphabetic |
|
|
| Is the string alphabetic? 0 if yes, 1 if no. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_alphabetic(struct fld_desc *f, char *s)
|
|
{
|
|
unsigned int i;
|
|
char c;
|
|
|
|
for (i = 0; i < f->len; i++)
|
|
{
|
|
c = s[i];
|
|
if (!((c == ' ') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c
|
|
<= 'Z'))))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_upper |
|
|
| Is the string in upper case? 0 if yes, 1 if no. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_upper(struct fld_desc *f, char *s)
|
|
{
|
|
unsigned int i;
|
|
char c;
|
|
|
|
for (i = 0; i < f->len; i++)
|
|
{
|
|
c = s[i];
|
|
if (!((c == ' ') || ((c >= 'A') && (c <= 'Z'))))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_lower |
|
|
| Is the string in lower case? 0 if yes, 1 if no. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_lower(struct fld_desc *f, char *s)
|
|
{
|
|
unsigned int i;
|
|
char c;
|
|
|
|
for (i = 0; i < f->len; i++)
|
|
{
|
|
c = s[i];
|
|
if (!((c == ' ') || ((c >= 'a') && (c <= 'z'))))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_check_condition |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_check_condition(struct fld_desc *f1, char *s1, ...)
|
|
{
|
|
struct fld_desc *f2, *f3;
|
|
char *s2, *s3;
|
|
int ret = 1; /* assume wrong */
|
|
va_list args;
|
|
double fp1, fp2, fp3;
|
|
|
|
va_start(args, s1);
|
|
f2 = va_arg(args, struct fld_desc *);
|
|
while (f2)
|
|
{
|
|
s2 = va_arg(args, char *);
|
|
f3 = va_arg(args, struct fld_desc *);
|
|
s3 = va_arg(args, char *);
|
|
|
|
if (f1->type == DTYPE_DISPLAY || f1->type == DTYPE_BININT)
|
|
{
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
tcob_fldtod(f3, s3, &fp3);
|
|
if ((fp1 >= fp2 && fp1 <= fp3))
|
|
{
|
|
ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tcob_compare(f1, s1, f2, s2) > -1 && tcob_compare(f1, s1, f3,
|
|
s3) < 1)
|
|
{
|
|
ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
f2 = va_arg(args, struct fld_desc *);
|
|
}
|
|
va_end(args);
|
|
return ret;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_compare_doubles |
|
|
| retorna 1 se d1>d2; 0 se d1==d2; -1 se d1<d2 |
|
|
| return 1 if d1>d2; 0 if d1==d2; -1 if d1<d2 |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_compare_doubles(double d1, double d2)
|
|
{
|
|
if (d1 > d2)
|
|
return 1;
|
|
if (d2 > d1)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| compare_all |
|
|
| retorna 1 se s1>d2; 0 se s1==s2; -1 se s1<s2 |
|
|
| return 1 if s1>s2; 0 if s1==s2; -1 if s1<s2 |
|
|
| s1 and s2 must be compared unsigned otherwise High-value compares |
|
|
| less than Low-value. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
static int
|
|
compare_all(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2)
|
|
{
|
|
unsigned int i, j, k, maxi;
|
|
unsigned char *us1 = (unsigned char *) s1, *us2 = (unsigned char *) s2;
|
|
|
|
maxi = (f1->len < f2->len) ? f1->len : f2->len; /* min (f1->len, f2->len) */
|
|
j = 0;
|
|
k = 0;
|
|
for (i = 0; i < maxi; i++)
|
|
{
|
|
if (us1[j] == us2[k])
|
|
continue;
|
|
if (us1[j] > us2[k])
|
|
return 1;
|
|
if (us1[j] < us2[k])
|
|
return -1;
|
|
j++;
|
|
k++;
|
|
if (f1->all && j >= f1->len)
|
|
j = 0;
|
|
if (f2->all && k >= f2->len)
|
|
k = 0;
|
|
}
|
|
|
|
if (f1->len > f2->len)
|
|
while (j < f1->len)
|
|
{
|
|
if (us1[j++] != us2[k++])
|
|
return 1;
|
|
if (k >= f2->len)
|
|
k = 0;
|
|
}
|
|
else
|
|
while (k < f2->len)
|
|
{
|
|
if (us2[k++] != us1[j++])
|
|
return -1;
|
|
if (j >= f1->len)
|
|
j = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_compare |
|
|
| retorna 1 se s1>s2; 0 se s1==s2; -1 se s1<s2 |
|
|
| return 1 if s1>s2; 0 if s1==s2; -1 if s1<s2 |
|
|
| s1 and s2 must be declared unsigned otherwise High-value compares |
|
|
| less than Low-value.
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
int
|
|
tcob_compare(struct fld_desc *f1, char *s1, struct fld_desc *f2, char *s2)
|
|
{
|
|
unsigned int i, maxi;
|
|
double fp1, fp2;
|
|
char c1, c2;
|
|
unsigned char *us1 = (unsigned char *) s1, *us2 = (unsigned char *) s2;
|
|
|
|
if ((f1->type == DTYPE_ALPHANUMERIC || f1->type == DTYPE_GROUP)
|
|
&& (f2->type == DTYPE_ALPHANUMERIC || f2->type == DTYPE_GROUP))
|
|
{ /* compare strings */
|
|
if (f1->all || f2->all)
|
|
return (compare_all(f1, s1, f2, s2));
|
|
maxi = (f1->len < f2->len) ? f1->len : f2->len; /* min (f1->len, f2->len) */
|
|
for (i = 0; i < maxi; i++)
|
|
{
|
|
if (us1[i] == us2[i])
|
|
continue;
|
|
if (us1[i] > us2[i])
|
|
return 1;
|
|
if (us1[i] < us2[i])
|
|
return -1;
|
|
}
|
|
if (f1->len > f2->len)
|
|
for (; i < f1->len; i++)
|
|
{
|
|
if (us1[i] != ' ')
|
|
return 1;
|
|
}
|
|
else
|
|
for (; i < f2->len; i++)
|
|
{
|
|
if (us2[i] != ' ')
|
|
return -1;
|
|
}
|
|
}
|
|
else if ((f1->type != DTYPE_DISPLAY && f1->type != DTYPE_PACKED && f1->type
|
|
!= DTYPE_BININT) || (f2->type != DTYPE_DISPLAY && f2->type
|
|
!= DTYPE_PACKED && f2->type != DTYPE_BININT))
|
|
{ /* compare strings */
|
|
if (f1->all || f2->all)
|
|
return (compare_all(f1, s1, f2, s2));
|
|
maxi = (f1->len < f2->len) ? f1->len : f2->len; /* min (f1->len, f2->len) */
|
|
for (i = 0; i < maxi; i++)
|
|
{
|
|
if (us1[i] == us2[i])
|
|
continue;
|
|
c1 = s1[i];
|
|
c2 = s2[i];
|
|
/* ignore the signs if any */
|
|
if (f1->type == DTYPE_DISPLAY && tcob_picElemVal(f1->pic, 0) == 'S')
|
|
{
|
|
c1 = (char) tcob_char_to_sign(c1);
|
|
c1 = c1 < 0 ? (c1 * -1) + '0' : c1 + '0';
|
|
}
|
|
if (f2->type == DTYPE_DISPLAY && tcob_picElemVal(f2->pic, 0) == 'S')
|
|
{
|
|
c2 = (char) tcob_char_to_sign(c2);
|
|
c2 = c2 < 0 ? (c2 * -1) + '0' : c2 + '0';
|
|
}
|
|
if (c1 == c2)
|
|
continue;
|
|
if (c1 > c2)
|
|
return 1;
|
|
if (c1 < c2)
|
|
return -1;
|
|
}
|
|
if (f1->len > f2->len)
|
|
for (; i < f1->len; i++)
|
|
{
|
|
if (us1[i] != ' ')
|
|
return 1;
|
|
}
|
|
else
|
|
for (; i < f2->len; i++)
|
|
{
|
|
if (us2[i] != ' ')
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tcob_fldtod(f1, s1, &fp1);
|
|
tcob_fldtod(f2, s2, &fp2);
|
|
if (fp1 > fp2)
|
|
return 1;
|
|
if (fp2 > fp1)
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_assign_int |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void
|
|
tcob_assign_int(struct fld_desc *desc, char *val, int value)
|
|
{
|
|
tcob_move(&_generic_4binary, (char *) & value, desc, val);
|
|
}
|
|
|
|
/* end of MCMATH.C */
|
|
|