2 * lib_util - calc library utility routines
4 * Copyright (C) 1999-2006 Landon Curt Noll
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 * Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.1 $
21 * @(#) $Id: lib_util.c,v 30.1 2007/03/16 11:09:46 chongo Exp $
22 * @(#) $Source: /usr/local/src/bin/calc/RCS/lib_util.c,v $
24 * Under source code control: 1997/04/19 21:38:30
25 * File existed as early as: 1997
27 * chongo <was here> /\oo/\ http://www.isthe.com/chongo/
28 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
32 * These routines are here to support users of libcalc.a. These routines
33 * are not directly used by calc itself, however.
42 * lowhex2bin - quick low order ASCII hex to binary conversion
44 * We just use mod 16 for non-hex ASCII chars. We use just mod 128
45 * for non-ASCII to ASCII conversion.
47 * | 00 nul | 01 soh | 02 stx | 03 etx | 04 eot | 05 enq | 06 ack | 07 bel |
48 * | 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si |
49 * | 10 dle | 11 dc1 | 12 dc2 | 13 dc3 | 14 dc4 | 15 nak | 16 syn | 17 etb |
50 * | 18 can | 19 em | 1a sub | 1b esc | 1c fs | 1d gs | 1e rs | 1f us |
51 * | 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' |
52 * | 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / |
53 * | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 |
54 * | 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? |
55 * | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G |
56 * | 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O |
57 * | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W |
58 * | 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ |
59 * | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g |
60 * | 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o |
61 * | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w |
62 * | 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del |
64 int lowhex2bin
[256] = {
65 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
66 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 0 */
67 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 1 */
68 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 2 */
69 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 3 */
70 0x0,0xa,0xb,0xc,0xd,0xe,0xf,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 4 */
71 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 5 */
72 0x0,0xa,0xb,0xc,0xd,0xe,0xf,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 6 */
73 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 7 */
74 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 8 */
75 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* 9 */
76 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* a */
77 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* b */
78 0x0,0xa,0xb,0xc,0xd,0xe,0xf,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* c */
79 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* d */
80 0x0,0xa,0xb,0xc,0xd,0xe,0xf,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, /* e */
81 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf /* f */
86 * hex2bin - macro to convert two ASCII hex chars into binary value
89 * high - high order hex ASCII char
90 * low - low order hex ASCII char
93 * numeric equivalent to 0x{high}{low} as an int
95 #define hex2bin(high,low) \
96 (lowhex2bin[(int)((char)(high))]<<4 | lowhex2bin[((int)(char)(low))])
99 * lowbin2hex - quick low order binary conversion to ASCII hex
101 char lowbin2hex
[256] = {
102 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
103 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
104 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
105 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
106 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
107 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
108 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
109 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
110 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
111 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
112 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
113 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
114 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
115 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
116 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
117 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
122 * convstr2z - convert a string into a ZVALUE
124 * NOTE: No attempt is make to deal with byte order.
127 * str string to convert
135 HALF
*v
; /* storage for string as HALFs */
136 ZVALUE ret
; /* return value */
137 size_t len
; /* length in HALFs of our string rounded up */
142 if (str
== NULL
|| *str
== '\0') {
143 /* NULL or empty strings return 0 */
148 * allocate HALF strorage
150 len
= (strlen(str
)+sizeof(HALF
)-1)/sizeof(HALF
);
151 v
= (HALF
*)malloc(len
* sizeof(HALF
));
153 math_error("convstr2z bad malloc");
156 v
[len
-1] = 0; /* deal with possible partial end of string HALF */
159 * initialize HALF array with string value
161 memcpy((void *)v
, (void *)str
, strlen(str
));
164 * setup the rest of the ZVALUE
179 * convhex2z - convert hex string to ZVALUE
182 * str hex ASCII string with optional leading 0x
190 HALF
*v
; /* storage for string as HALFs */
191 HALF
*hp
; /* HALF pointer */
192 char *sp
; /* string pointer */
193 ZVALUE ret
; /* return value */
194 int len
; /* length in HALFs of our string rounded up */
195 size_t slen
; /* hex string length */
201 if (hex
== NULL
|| hex
[0] == '\0') {
202 /* NULL or empty strings return 0 */
207 * skip leading 0X or 0x if needed
209 if (hex
[0] == '0' && (hex
[1] == 'x' || hex
[1] == 'X')) {
212 if (hex
[0] == '\0') {
213 /* just 0X or 0x returns 0 */
218 * allocate HALF strorage
221 len
= ((slen
*4)+BASEB
-1)/BASEB
;
222 v
= (HALF
*)malloc(len
* sizeof(HALF
));
224 math_error("convhex2z bad malloc");
227 v
[len
-1] = 0; /* deal with possible partial end of string HALF */
230 * deal with the upper partial HALF value
234 if ((slen
% (BASEB
/4)) != 0) {
236 /* deal with a odd length hex string first */
238 *hp
= hex2bin('0', *sp
++);
241 /* even length - top top hex char to process */
245 /* slen is even now */
247 /* eat two hex chars at a time until the HALF is full */
248 for (; (slen
% (BASEB
/4)) != 0; slen
-= 2, sp
+= 2) {
249 *hp
= ((*hp
<<8) | hex2bin(sp
[0], sp
[1]));
252 /* move on to the next HALF */
255 /* slen is now a multiple of BASEB/4 */
258 * deal with full HALFs
260 for (; slen
> 0; slen
-= (BASEB
/4), --hp
) {
265 /* eat two hex chars at a time until the HALF is full */
266 for (i
=0; i
< (BASEB
/4); i
+= 2) {
267 *hp
= ((*hp
<<8) | hex2bin(sp
[i
], sp
[i
+1]));
272 * setup the rest of the ZVALUE
287 * convz2hex - convert ZVALUE to hex string
289 * We will ignore the sign of the value.
295 * str hex ASCII malloced string (without a leading 0x)
300 char *ret
; /* string to return */
301 int slen
; /* string length (not counting \0) */
302 HALF half
; /* HALF value to convert */
303 int seen_nz
; /* 0 => we have not seen a non-zero hex char (yet) */
311 if (z
.v
== NULL
|| ziszero(z
)) {
312 /* malloc and return "0" */
313 ret
= (char *)malloc(sizeof("0"));
315 math_error("convz2hex bad malloc of 0 value");
324 * malloc string storage
326 slen
= (z
.len
* BASEB
/4);
327 ret
= (char *)calloc(slen
+1+1, sizeof(char));
329 math_error("convz2hex bad malloc of string");
334 * load in hex ASCII chars for each HALF
336 * We will not write leading '0' hex chars into the string.
339 for (p
=ret
, i
=z
.len
-1; i
>= 0; --i
) {
342 * load in ASCII hex by ASCII hex
344 for (half
=z
.v
[i
], j
=BASEB
-4; j
>= 0; j
-=4) {
346 /* we saw a non-zero, just load the rest */
347 *p
++ = lowbin2hex
[(half
>> j
) & 0xff];
349 /* all zeros so far */
350 *p
= lowbin2hex
[(half
>> j
) & 0xff];
352 /* we found our first non-zero char */
362 /* saw nothing but 0's, so just return 0 */
368 * return the new string