Mercurial > hg > CbC > CbC_gcc
annotate libdecnumber/decPacked.c @ 144:8f4e72ab4e11
fix segmentation fault caused by nothing next cur_op to end
author | Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 23 Dec 2018 21:23:56 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 /* Packed decimal conversion module for the decNumber C Library. |
131 | 2 Copyright (C) 2007-2018 Free Software Foundation, Inc. |
0 | 3 Contributed by IBM Corporation. Author Mike Cowlishaw. |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under | |
8 the terms of the GNU General Public License as published by the Free | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 Under Section 7 of GPL version 3, you are granted additional | |
18 permissions described in the GCC Runtime Library Exception, version | |
19 3.1, as published by the Free Software Foundation. | |
20 | |
21 You should have received a copy of the GNU General Public License and | |
22 a copy of the GCC Runtime Library Exception along with this program; | |
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
24 <http://www.gnu.org/licenses/>. */ | |
25 | |
26 /* ------------------------------------------------------------------ */ | |
27 /* Packed Decimal conversion module */ | |
28 /* ------------------------------------------------------------------ */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
29 /* This module comprises the routines for Packed Decimal format */ |
0 | 30 /* numbers. Conversions are supplied to and from decNumber, which in */ |
31 /* turn supports: */ | |
32 /* conversions to and from string */ | |
33 /* arithmetic routines */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
34 /* utilities. */ |
0 | 35 /* Conversions from decNumber to and from densely packed decimal */ |
36 /* formats are provided by the decimal32 through decimal128 modules. */ | |
37 /* ------------------------------------------------------------------ */ | |
38 | |
39 #include <string.h> /* for NULL */ | |
40 #include "decNumber.h" /* base number library */ | |
41 #include "decPacked.h" /* packed decimal */ | |
42 #include "decNumberLocal.h" /* decNumber local types, etc. */ | |
43 | |
44 /* ------------------------------------------------------------------ */ | |
45 /* decPackedFromNumber -- convert decNumber to BCD Packed Decimal */ | |
46 /* */ | |
47 /* bcd is the BCD bytes */ | |
48 /* length is the length of the BCD array */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
49 /* scale is the scale result */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
50 /* dn is the decNumber */ |
0 | 51 /* returns bcd, or NULL if error */ |
52 /* */ | |
53 /* The number is converted to a BCD packed decimal byte array, */ | |
54 /* right aligned in the bcd array, whose length is indicated by the */ | |
55 /* second parameter. The final 4-bit nibble in the array will be a */ | |
56 /* sign nibble, C (1100) for + and D (1101) for -. Unused bytes and */ | |
57 /* nibbles to the left of the number are set to 0. */ | |
58 /* */ | |
59 /* scale is set to the scale of the number (this is the exponent, */ | |
60 /* negated). To force the number to a specified scale, first use the */ | |
61 /* decNumberRescale routine, which will round and change the exponent */ | |
62 /* as necessary. */ | |
63 /* */ | |
64 /* If there is an error (that is, the decNumber has too many digits */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
65 /* to fit in length bytes, or it is a NaN or Infinity), NULL is */ |
0 | 66 /* returned and the bcd and scale results are unchanged. Otherwise */ |
67 /* bcd is returned. */ | |
68 /* ------------------------------------------------------------------ */ | |
69 uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, | |
70 const decNumber *dn) { | |
71 const Unit *up=dn->lsu; /* Unit array pointer */ | |
72 uByte obyte, *out; /* current output byte, and where it goes */ | |
73 Int indigs=dn->digits; /* digits processed */ | |
74 uInt cut=DECDPUN; /* downcounter per Unit */ | |
75 uInt u=*up; /* work */ | |
76 uInt nib; /* .. */ | |
77 #if DECDPUN<=4 | |
78 uInt temp; /* .. */ | |
79 #endif | |
80 | |
81 if (dn->digits>length*2-1 /* too long .. */ | |
82 ||(dn->bits & DECSPECIAL)) return NULL; /* .. or special -- hopeless */ | |
83 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
84 if (dn->bits&DECNEG) obyte=DECPMINUS; /* set the sign .. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
85 else obyte=DECPPLUS; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
86 *scale=-dn->exponent; /* .. and scale */ |
0 | 87 |
88 /* loop from lowest (rightmost) byte */ | |
89 out=bcd+length-1; /* -> final byte */ | |
90 for (; out>=bcd; out--) { | |
91 if (indigs>0) { | |
92 if (cut==0) { | |
93 up++; | |
94 u=*up; | |
95 cut=DECDPUN; | |
96 } | |
97 #if DECDPUN<=4 | |
98 temp=(u*6554)>>16; /* fast /10 */ | |
99 nib=u-X10(temp); | |
100 u=temp; | |
101 #else | |
102 nib=u%10; /* cannot use *6554 trick :-( */ | |
103 u=u/10; | |
104 #endif | |
105 obyte|=(nib<<4); | |
106 indigs--; | |
107 cut--; | |
108 } | |
109 *out=obyte; | |
110 obyte=0; /* assume 0 */ | |
111 if (indigs>0) { | |
112 if (cut==0) { | |
113 up++; | |
114 u=*up; | |
115 cut=DECDPUN; | |
116 } | |
117 #if DECDPUN<=4 | |
118 temp=(u*6554)>>16; /* as above */ | |
119 obyte=(uByte)(u-X10(temp)); | |
120 u=temp; | |
121 #else | |
122 obyte=(uByte)(u%10); | |
123 u=u/10; | |
124 #endif | |
125 indigs--; | |
126 cut--; | |
127 } | |
128 } /* loop */ | |
129 | |
130 return bcd; | |
131 } /* decPackedFromNumber */ | |
132 | |
133 /* ------------------------------------------------------------------ */ | |
134 /* decPackedToNumber -- convert BCD Packed Decimal to a decNumber */ | |
135 /* */ | |
136 /* bcd is the BCD bytes */ | |
137 /* length is the length of the BCD array */ | |
138 /* scale is the scale associated with the BCD integer */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
139 /* dn is the decNumber [with space for length*2 digits] */ |
0 | 140 /* returns dn, or NULL if error */ |
141 /* */ | |
142 /* The BCD packed decimal byte array, together with an associated */ | |
143 /* scale, is converted to a decNumber. The BCD array is assumed full */ | |
144 /* of digits, and must be ended by a 4-bit sign nibble in the least */ | |
145 /* significant four bits of the final byte. */ | |
146 /* */ | |
147 /* The scale is used (negated) as the exponent of the decNumber. */ | |
148 /* Note that zeros may have a sign and/or a scale. */ | |
149 /* */ | |
150 /* The decNumber structure is assumed to have sufficient space to */ | |
151 /* hold the converted number (that is, up to length*2-1 digits), so */ | |
152 /* no error is possible unless the adjusted exponent is out of range, */ | |
153 /* no sign nibble was found, or a sign nibble was found before the */ | |
154 /* final nibble. In these error cases, NULL is returned and the */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
155 /* decNumber will be 0. */ |
0 | 156 /* ------------------------------------------------------------------ */ |
157 decNumber * decPackedToNumber(const uByte *bcd, Int length, | |
158 const Int *scale, decNumber *dn) { | |
159 const uByte *last=bcd+length-1; /* -> last byte */ | |
160 const uByte *first; /* -> first non-zero byte */ | |
161 uInt nib; /* work nibble */ | |
162 Unit *up=dn->lsu; /* output pointer */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
163 Int digits; /* digits count */ |
0 | 164 Int cut=0; /* phase of output */ |
165 | |
166 decNumberZero(dn); /* default result */ | |
167 last=&bcd[length-1]; | |
168 nib=*last & 0x0f; /* get the sign */ | |
169 if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG; | |
170 else if (nib<=9) return NULL; /* not a sign nibble */ | |
171 | |
172 /* skip leading zero bytes [final byte is always non-zero, due to sign] */ | |
173 for (first=bcd; *first==0;) first++; | |
174 digits=(last-first)*2+1; /* calculate digits .. */ | |
175 if ((*first & 0xf0)==0) digits--; /* adjust for leading zero nibble */ | |
176 if (digits!=0) dn->digits=digits; /* count of actual digits [if 0, */ | |
177 /* leave as 1] */ | |
178 | |
179 /* check the adjusted exponent; note that scale could be unbounded */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
180 dn->exponent=-*scale; /* set the exponent */ |
0 | 181 if (*scale>=0) { /* usual case */ |
182 if ((dn->digits-*scale-1)<-DECNUMMAXE) { /* underflow */ | |
183 decNumberZero(dn); | |
184 return NULL;} | |
185 } | |
186 else { /* -ve scale; +ve exponent */ | |
187 /* need to be careful to avoid wrap, here, also BADINT case */ | |
188 if ((*scale<-DECNUMMAXE) /* overflow even without digits */ | |
189 || ((dn->digits-*scale-1)>DECNUMMAXE)) { /* overflow */ | |
190 decNumberZero(dn); | |
191 return NULL;} | |
192 } | |
193 if (digits==0) return dn; /* result was zero */ | |
194 | |
195 /* copy the digits to the number's units, starting at the lsu */ | |
196 /* [unrolled] */ | |
197 for (;;) { /* forever */ | |
198 /* left nibble first */ | |
199 nib=(unsigned)(*last & 0xf0)>>4; | |
200 /* got a digit, in nib */ | |
201 if (nib>9) {decNumberZero(dn); return NULL;} | |
202 | |
203 if (cut==0) *up=(Unit)nib; | |
204 else *up=(Unit)(*up+nib*DECPOWERS[cut]); | |
205 digits--; | |
206 if (digits==0) break; /* got them all */ | |
207 cut++; | |
208 if (cut==DECDPUN) { | |
209 up++; | |
210 cut=0; | |
211 } | |
212 last--; /* ready for next */ | |
213 nib=*last & 0x0f; /* get right nibble */ | |
214 if (nib>9) {decNumberZero(dn); return NULL;} | |
215 | |
216 /* got a digit, in nib */ | |
217 if (cut==0) *up=(Unit)nib; | |
218 else *up=(Unit)(*up+nib*DECPOWERS[cut]); | |
219 digits--; | |
220 if (digits==0) break; /* got them all */ | |
221 cut++; | |
222 if (cut==DECDPUN) { | |
223 up++; | |
224 cut=0; | |
225 } | |
226 } /* forever */ | |
227 | |
228 return dn; | |
229 } /* decPackedToNumber */ | |
230 |