5
* Copyright (C) 1999 - 2007 Michael C. Ring
7
* Permission to use, copy, and distribute this software and its
8
* documentation for any purpose with or without fee is hereby granted,
9
* provided that the above copyright notice appear in all copies and
10
* that both that copyright notice and this permission notice appear
11
* in supporting documentation.
13
* Permission to modify the software is granted. Permission to distribute
14
* the modified code is granted. Modifications are to be distributed by
15
* using the file 'license.txt' as a template to modify the file header.
16
* 'license.txt' is available in the official MAPM distribution.
18
* This software is provided "as is" without express or implied warranty.
23
* This file contains the functions necessary to get C 'longs' and
24
* 'strings' into the MAPM number system. It also contains the function
25
* to get a string from a MAPM number.
30
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
32
static char *M_buf = NULL;
33
static int M_lbuf = 0;
34
static const char *M_set_string_error_msg = "\'m_apm_set_string\', Out of memory";
36
/****************************************************************************/
46
/****************************************************************************/
47
void m_apm_set_long(M_APM atmp, long mm)
50
char *p, *buf, ch, buf2[64];
52
/* if zero, return right away */
60
M_long_2_ascii(buf2, mm); /* convert long -> ascii in base 10 */
65
atmp->m_apm_sign = -1;
66
buf++; /* get past '-' sign */
74
atmp->m_apm_exponent = len;
76
/* least significant nibble of ODD data-length must be 0 */
83
/* remove any trailing '0' ... */
87
if (buf[--len] != '0')
91
atmp->m_apm_datalength = ++len;
93
nbytes = (len + 1) >> 1;
96
for (ii=0; ii < nbytes; ii++)
99
atmp->m_apm_data[ii] = 10 * ch + *p++ - '0';
102
/****************************************************************************/
103
void m_apm_set_string(M_APM ctmp, const char *s_in)
105
char ch, *cp, *s, *p;
107
int i, j, zflag, exponent, sign;
112
if ((M_buf = (char *)MAPM_MALLOC(256)) == NULL)
114
/* fatal, this does not return */
116
M_apm_log_error_msg(M_APM_FATAL, M_set_string_error_msg);
120
if ((i = strlen(s_in)) > (M_lbuf - 4))
123
if ((vp = MAPM_REALLOC(M_buf, M_lbuf)) == NULL)
125
/* fatal, this does not return */
127
M_apm_log_error_msg(M_APM_FATAL, M_set_string_error_msg);
136
/* default == zero ... */
144
if (*p == ' ' || *p == '\t')
153
sign = 1; /* assume number is positive */
155
if (*p == '+') /* scan by optional '+' sign */
159
if (*p == '-') /* check if number negative */
166
M_lowercase(p); /* convert string to lowercase */
167
exponent = 0; /* default */
169
if ((cp = strstr(p,"e")) != NULL)
171
exponent = atoi(cp + sizeof(char));
172
*cp = '\0'; /* erase the exponent now */
175
j = M_strposition(p, (char *) "."); /* is there a decimal point ?? */
178
strcat(p,"."); /* if not, append one */
179
j = M_strposition(p, (char *) "."); /* now find it ... */
182
if (j > 0) /* normalize number and adjust exponent */
185
memmove((p+1),p,(j * sizeof(char)));
188
p++; /* scan past implied decimal point now in column 1 (index 0) */
191
ctmp->m_apm_datalength = i;
193
if ((i & 1) != 0) /* if odd number of digits, append a '0' to make it even */
196
j = strlen(p) >> 1; /* number of bytes in encoded M_APM number */
198
/* do we need more memory to hold this number */
200
if (j > ctmp->m_apm_malloclength)
202
if ((vp = MAPM_REALLOC(ctmp->m_apm_data, (j + 32))) == NULL)
204
/* fatal, this does not return */
206
M_apm_log_error_msg(M_APM_FATAL, M_set_string_error_msg);
209
ctmp->m_apm_malloclength = j + 28;
210
ctmp->m_apm_data = (UCHAR *)vp;
215
for (i=0; i < j; i++)
218
if ((ch = (10 * ch + *p++ - '0')) != 0)
221
if (((int)ch & 0xFF) >= 100)
223
M_apm_log_error_msg(M_APM_RETURN,
224
"\'m_apm_set_string\', Non-digit char found in parse");
226
M_apm_log_error_msg(M_APM_RETURN, "Text =");
227
M_apm_log_error_msg(M_APM_RETURN, s_in);
233
ctmp->m_apm_data[i] = ch;
234
ctmp->m_apm_data[i+1] = 0;
237
ctmp->m_apm_exponent = exponent;
238
ctmp->m_apm_sign = sign;
242
ctmp->m_apm_exponent = 0;
243
ctmp->m_apm_sign = 0;
244
ctmp->m_apm_datalength = 1;
248
M_apm_normalize(ctmp);
252
* if our local temp string is getting too big,
253
* release it's memory and start over next time.
254
* (this 1000 byte threshold is quite arbitrary,
255
* it may be more efficient in your app to make
256
* this number bigger).
266
/****************************************************************************/
267
void m_apm_to_string(char *s, int places, M_APM mtmp)
271
int i, index, first, max_i, num_digits, dec_places;
272
UCHAR numdiv, numrem;
274
ctmp = M_get_stack_var();
278
m_apm_copy(ctmp, mtmp);
280
m_apm_round(ctmp, dec_places, mtmp);
282
if (ctmp->m_apm_sign == 0)
293
for (i=0; i < dec_places; i++)
303
max_i = (ctmp->m_apm_datalength + 1) >> 1;
306
num_digits = ctmp->m_apm_datalength;
308
num_digits = dec_places + 1;
312
if (ctmp->m_apm_sign == -1)
328
M_get_div_rem_10((int)ctmp->m_apm_data[index],&numdiv,&numrem);
332
*cp++ = numdiv + '0';
334
if (++i == num_digits)
343
*cp++ = numrem + '0';
345
if (++i == num_digits)
349
i = ctmp->m_apm_exponent - 1;
351
sprintf(cp,"E+%d",i);
357
/****************************************************************************/