1 /*-------------------------------------------------------------------------
4 * utility functions for I/O of built-in numeric types.
7 * floating point: ftoa, atof1
9 * Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/utils/adt/numutils.c,v 1.8 1996/12/28 02:12:17 momjian Exp $
15 *-------------------------------------------------------------------------
17 #include <stdio.h> /* for sprintf() */
21 #include "utils/builtins.h" /* where the declarations go */
23 # include <regex/utils.h>
27 #include <port-protos.h> /* ecvt(), fcvt() */
30 pg_atoi(char *s, int size, int c)
33 char *badp = (char *) NULL;
38 l = strtol(s, &badp, 10);
39 if (errno) /* strtol must set ERANGE */
40 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
41 if (badp && *badp && (*badp != c))
42 elog(WARN, "pg_atoi: error in \"%s\": can\'t parse \"%s\"", s, badp);
47 /* won't get ERANGE on these with 64-bit longs... */
48 if (l < -0x80000000L) {
50 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
52 if (l > 0x7fffffffL) {
54 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
56 #endif /* HAS_LONG_LONG */
61 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
65 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
71 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
75 elog(WARN, "pg_atoi: error reading \"%s\": %m", s);
79 elog(WARN, "pg_atoi: invalid result size: %d", size);
85 * itoa - converts a short int to its string represention
88 * previously based on ~ingres/source/gutil/atoi.c
89 * now uses vendor's sprintf conversion
94 sprintf(a, "%hd", (short)i);
98 * ltoa - converts a long int to its string represention
101 * previously based on ~ingres/source/gutil/atoi.c
102 * now uses vendor's sprintf conversion
105 ltoa(int32 l, char *a)
111 ** ftoa - FLOATING POINT TO ASCII CONVERSION
113 ** CODE derived from ingres, ~ingres/source/gutil/ftoa.c
115 ** 'Value' is converted to an ascii character string and stored
116 ** into 'ascii'. Ascii should have room for at least 'width' + 1
117 ** characters. 'Width' is the width of the output field (max).
118 ** 'Prec' is the number of characters to put after the decimal
119 ** point. The format of the output string is controlled by
123 ** e or E: "E" format output
124 ** f or F: "F" format output
125 ** g or G: "F" format output if it will fit, otherwise
127 ** n or N: same as G, but decimal points will not always
130 ** If 'format' is upper case, the "E" comes out in upper case;
131 ** otherwise it comes out in lower case.
133 ** When the field width is not big enough, it fills the field with
134 ** stars ("*****") and returns zero. Normal return is the width
135 ** of the output field (sometimes shorter than 'width').
138 ftoa(double value, char *ascii, int width, int prec1, char format)
140 #if defined(BSD44_derived) || \
147 (void) sprintf(fmt, "%%%d.%d%c", width, prec1, format);
148 (void) sprintf(out, fmt, value);
149 if ((ret = strlen(out)) > width) {
150 memset(ascii, '*', width - 2);
154 (void) strcpy(ascii, out);
159 register int avail = 0;
160 register char *a = NULL;
161 register char *p = NULL;
165 /* extern char *ecvt(), *fcvt();*/
169 lowercase = 'a' - 'A';
176 /* try 'F' style output */
177 p = fcvt(value, prec, &expon, &sign);
187 /* output '0' before the decimal point */
193 /* compute space length left after dec pt and fraction */
198 if (avail >= expon) {
200 /* it fits. output */
202 /* output left of dp */
210 /* output fraction (right of dec pt) */
214 /* won't fit; let's hope for G format */
218 /* try to do E style output */
219 p = ecvt(value, prec + 1, &expon, &sign);
223 /* output the sign */
230 /* check for field too small */
231 if (mode == 'F' || avail < prec) {
232 /* sorry joker, you lose */
234 for (avail = width; avail > 0; avail--)
240 /* it fits; output the number */
243 /* output the LHS single digit */
265 /* output the exponent */
267 *a++ = 'E' + lowercase;
273 *a++ = (expon / 10) % 10 + '0';
274 *a++ = expon % 10 + '0';
277 /* output spaces on the end in G format */
285 /* finally, we can return */
289 #endif /* !BSD44_derived */
293 ** atof1 - ASCII TO FLOATING CONVERSION
295 ** CODE derived from ~ingres/source/gutil/atof.c
297 ** Converts the string 'str' to floating point and stores the
298 ** result into the cell pointed to by 'val'.
300 ** The syntax which it accepts is pretty much what you would
301 ** expect. Basically, it is:
302 ** {<sp>} [+|-] {<sp>} {<digit>} [.{digit}] {<sp>} [<exp>]
303 ** where <exp> is "e" or "E" followed by an integer, <sp> is a
304 ** space character, <digit> is zero through nine, [] is zero or
305 ** one, and {} is zero or more.
308 ** str -- string to convert.
309 ** val -- pointer to place to put the result (which
310 ** must be type double).
314 ** -1 -- syntax error.
315 ** +1 -- overflow (not implemented).
321 atof1(char *str, double *val)
329 register int gotmant;
335 /* skip leading blanks */
336 while ((c = *p) != '\0') {
342 /* handle possible sign */
351 /* skip blanks after sign */
352 while ((c = *p) != '\0') {
358 /* start collecting the number to the decimal point */
362 if (c < '0' || c > '9')
364 v = v * 10.0 + (c - '0');
369 /* check for fractional part */
374 if (c < '0' || c > '9')
377 v += (c - '0') * fact;
382 /* skip blanks before possible exponent */
383 while ((c = *p) != '\0') {
389 /* test for exponent */
390 if (c == 'e' || c == 'E') {
392 expon = pg_atoi(p, sizeof(expon), '\0');
396 v *= pow(10.0, fact);
398 /* if no exponent, then nothing */
403 /* store the result and exit */