Annotation of embedaddon/php/ext/bcmath/libbcmath/src/output.c, revision 1.1.1.1
1.1 misho 1: /* output.c: bcmath library file. */
2: /*
3: Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
4: Copyright (C) 2000 Philip A. Nelson
5:
6: This library is free software; you can redistribute it and/or
7: modify it under the terms of the GNU Lesser General Public
8: License as published by the Free Software Foundation; either
9: version 2 of the License, or (at your option) any later version.
10:
11: This library is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: Lesser General Public License for more details. (COPYING.LIB)
15:
16: You should have received a copy of the GNU Lesser General Public
17: License along with this library; if not, write to:
18:
19: The Free Software Foundation, Inc.
20: 59 Temple Place, Suite 330
21: Boston, MA 02111-1307 USA.
22:
23: You may contact the author by:
24: e-mail: philnelson@acm.org
25: us-mail: Philip A. Nelson
26: Computer Science Department, 9062
27: Western Washington University
28: Bellingham, WA 98226-9062
29:
30: *************************************************************************/
31:
32: #include <config.h>
33: #include <stdio.h>
34: #include <assert.h>
35: #include <stdlib.h>
36: #include <ctype.h>
37: #include <stdarg.h>
38: #include "bcmath.h"
39: #include "private.h"
40:
41:
42: /* The following routines provide output for bcd numbers package
43: using the rules of POSIX bc for output. */
44:
45: /* This structure is used for saving digits in the conversion process. */
46: typedef struct stk_rec {
47: long digit;
48: struct stk_rec *next;
49: } stk_rec;
50:
51: /* The reference string for digits. */
52: static char ref_str[] = "0123456789ABCDEF";
53:
54:
55: /* A special output routine for "multi-character digits." Exactly
56: SIZE characters must be output for the value VAL. If SPACE is
57: non-zero, we must output one space before the number. OUT_CHAR
58: is the actual routine for writing the characters. */
59:
60: void
61: bc_out_long (val, size, space, out_char)
62: long val;
63: int size, space;
64: #ifdef __STDC__
65: void (*out_char)(int);
66: #else
67: void (*out_char)();
68: #endif
69: {
70: char digits[40];
71: int len, ix;
72:
73: if (space) (*out_char) (' ');
74: snprintf(digits, sizeof(digits), "%ld", val);
75: len = strlen (digits);
76: while (size > len)
77: {
78: (*out_char) ('0');
79: size--;
80: }
81: for (ix=0; ix < len; ix++)
82: (*out_char) (digits[ix]);
83: }
84:
85: /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR
86: as the routine to do the actual output of the characters. */
87:
88: void
89: #ifdef __STDC__
90: bc_out_num (bc_num num, int o_base, void (*out_char)(int), int leading_zero TSRMLS_DC)
91: #else
92: bc_out_num (bc_num num, int o_base, void (*out_char)(), int leading_zero TSRMLS_DC)
93: #endif
94: {
95: char *nptr;
96: int index, fdigit, pre_space;
97: stk_rec *digits, *temp;
98: bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
99:
100: /* The negative sign if needed. */
101: if (num->n_sign == MINUS) (*out_char) ('-');
102:
103: /* Output the number. */
104: if (bc_is_zero (num TSRMLS_CC))
105: (*out_char) ('0');
106: else
107: if (o_base == 10)
108: {
109: /* The number is in base 10, do it the fast way. */
110: nptr = num->n_value;
111: if (num->n_len > 1 || *nptr != 0)
112: for (index=num->n_len; index>0; index--)
113: (*out_char) (BCD_CHAR(*nptr++));
114: else
115: nptr++;
116:
117: if (leading_zero && bc_is_zero (num TSRMLS_CC))
118: (*out_char) ('0');
119:
120: /* Now the fraction. */
121: if (num->n_scale > 0)
122: {
123: (*out_char) ('.');
124: for (index=0; index<num->n_scale; index++)
125: (*out_char) (BCD_CHAR(*nptr++));
126: }
127: }
128: else
129: {
130: /* special case ... */
131: if (leading_zero && bc_is_zero (num TSRMLS_CC))
132: (*out_char) ('0');
133:
134: /* The number is some other base. */
135: digits = NULL;
136: bc_init_num (&int_part TSRMLS_CC);
137: bc_divide (num, BCG(_one_), &int_part, 0 TSRMLS_CC);
138: bc_init_num (&frac_part TSRMLS_CC);
139: bc_init_num (&cur_dig TSRMLS_CC);
140: bc_init_num (&base TSRMLS_CC);
141: bc_sub (num, int_part, &frac_part, 0);
142: /* Make the INT_PART and FRAC_PART positive. */
143: int_part->n_sign = PLUS;
144: frac_part->n_sign = PLUS;
145: bc_int2num (&base, o_base);
146: bc_init_num (&max_o_digit TSRMLS_CC);
147: bc_int2num (&max_o_digit, o_base-1);
148:
149:
150: /* Get the digits of the integer part and push them on a stack. */
151: while (!bc_is_zero (int_part TSRMLS_CC))
152: {
153: bc_modulo (int_part, base, &cur_dig, 0 TSRMLS_CC);
154: /* PHP Change: malloc() -> emalloc() */
155: temp = (stk_rec *) emalloc (sizeof(stk_rec));
156: if (temp == NULL) bc_out_of_memory();
157: temp->digit = bc_num2long (cur_dig);
158: temp->next = digits;
159: digits = temp;
160: bc_divide (int_part, base, &int_part, 0 TSRMLS_CC);
161: }
162:
163: /* Print the digits on the stack. */
164: if (digits != NULL)
165: {
166: /* Output the digits. */
167: while (digits != NULL)
168: {
169: temp = digits;
170: digits = digits->next;
171: if (o_base <= 16)
172: (*out_char) (ref_str[ (int) temp->digit]);
173: else
174: bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char);
175: efree (temp);
176: }
177: }
178:
179: /* Get and print the digits of the fraction part. */
180: if (num->n_scale > 0)
181: {
182: (*out_char) ('.');
183: pre_space = 0;
184: t_num = bc_copy_num (BCG(_one_));
185: while (t_num->n_len <= num->n_scale) {
186: bc_multiply (frac_part, base, &frac_part, num->n_scale TSRMLS_CC);
187: fdigit = bc_num2long (frac_part);
188: bc_int2num (&int_part, fdigit);
189: bc_sub (frac_part, int_part, &frac_part, 0);
190: if (o_base <= 16)
191: (*out_char) (ref_str[fdigit]);
192: else {
193: bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
194: pre_space = 1;
195: }
196: bc_multiply (t_num, base, &t_num, 0 TSRMLS_CC);
197: }
198: bc_free_num (&t_num);
199: }
200:
201: /* Clean up. */
202: bc_free_num (&int_part);
203: bc_free_num (&frac_part);
204: bc_free_num (&base);
205: bc_free_num (&cur_dig);
206: bc_free_num (&max_o_digit);
207: }
208: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>