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>