xref: /titanic_52/usr/src/common/ficl/utility.c (revision 608e6d6630e5027b8b9841e5977499815ed63f64)
1a1bf3f78SToomas Soome #include "ficl.h"
2*608e6d66SToomas Soome #include <limits.h>
3a1bf3f78SToomas Soome 
4a1bf3f78SToomas Soome /*
5a1bf3f78SToomas Soome  * a l i g n P t r
6a1bf3f78SToomas Soome  * Aligns the given pointer to FICL_ALIGN address units.
7a1bf3f78SToomas Soome  * Returns the aligned pointer value.
8a1bf3f78SToomas Soome  */
9a1bf3f78SToomas Soome void *
10a1bf3f78SToomas Soome ficlAlignPointer(void *ptr)
11a1bf3f78SToomas Soome {
12a1bf3f78SToomas Soome #if FICL_PLATFORM_ALIGNMENT > 1
13a1bf3f78SToomas Soome 	intptr_t p = (intptr_t)ptr;
14a1bf3f78SToomas Soome 
15a1bf3f78SToomas Soome 	if (p & (FICL_PLATFORM_ALIGNMENT - 1))
16a1bf3f78SToomas Soome 		ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) +
17a1bf3f78SToomas Soome 		    FICL_PLATFORM_ALIGNMENT);
18a1bf3f78SToomas Soome #endif
19a1bf3f78SToomas Soome 	return (ptr);
20a1bf3f78SToomas Soome }
21a1bf3f78SToomas Soome 
22a1bf3f78SToomas Soome /*
23a1bf3f78SToomas Soome  * s t r r e v
24a1bf3f78SToomas Soome  */
25a1bf3f78SToomas Soome char *
26a1bf3f78SToomas Soome ficlStringReverse(char *string)
27a1bf3f78SToomas Soome {
28a1bf3f78SToomas Soome 	int i = strlen(string);
29a1bf3f78SToomas Soome 	char *p1 = string;		/* first char of string */
30a1bf3f78SToomas Soome 	char *p2 = string + i - 1;	/* last non-NULL char of string */
31a1bf3f78SToomas Soome 	char c;
32a1bf3f78SToomas Soome 
33a1bf3f78SToomas Soome 	if (i > 1) {
34a1bf3f78SToomas Soome 		while (p1 < p2) {
35a1bf3f78SToomas Soome 			c = *p2;
36a1bf3f78SToomas Soome 			*p2 = *p1;
37a1bf3f78SToomas Soome 			*p1 = c;
38a1bf3f78SToomas Soome 			p1++; p2--;
39a1bf3f78SToomas Soome 		}
40a1bf3f78SToomas Soome 	}
41a1bf3f78SToomas Soome 
42a1bf3f78SToomas Soome 	return (string);
43a1bf3f78SToomas Soome }
44a1bf3f78SToomas Soome 
45a1bf3f78SToomas Soome /*
46a1bf3f78SToomas Soome  * d i g i t _ t o _ c h a r
47a1bf3f78SToomas Soome  */
48a1bf3f78SToomas Soome static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
49a1bf3f78SToomas Soome 
50a1bf3f78SToomas Soome char
51a1bf3f78SToomas Soome ficlDigitToCharacter(int value)
52a1bf3f78SToomas Soome {
53a1bf3f78SToomas Soome 	return (digits[value]);
54a1bf3f78SToomas Soome }
55a1bf3f78SToomas Soome 
56a1bf3f78SToomas Soome /*
57a1bf3f78SToomas Soome  * i s P o w e r O f T w o
58a1bf3f78SToomas Soome  * Tests whether supplied argument is an integer power of 2 (2**n)
59a1bf3f78SToomas Soome  * where 32 > n > 1, and returns n if so. Otherwise returns zero.
60a1bf3f78SToomas Soome  */
61a1bf3f78SToomas Soome int
62a1bf3f78SToomas Soome ficlIsPowerOfTwo(ficlUnsigned u)
63a1bf3f78SToomas Soome {
64a1bf3f78SToomas Soome 	int i = 1;
65a1bf3f78SToomas Soome 	ficlUnsigned t = 2;
66a1bf3f78SToomas Soome 
67a1bf3f78SToomas Soome 	for (; ((t <= u) && (t != 0)); i++, t <<= 1) {
68a1bf3f78SToomas Soome 		if (u == t)
69a1bf3f78SToomas Soome 			return (i);
70a1bf3f78SToomas Soome 	}
71a1bf3f78SToomas Soome 
72a1bf3f78SToomas Soome 	return (0);
73a1bf3f78SToomas Soome }
74a1bf3f78SToomas Soome 
75a1bf3f78SToomas Soome /*
76a1bf3f78SToomas Soome  * l t o a
77a1bf3f78SToomas Soome  */
78a1bf3f78SToomas Soome char *
79a1bf3f78SToomas Soome ficlLtoa(ficlInteger value, char *string, int radix)
80a1bf3f78SToomas Soome {
81a1bf3f78SToomas Soome 	char *cp = string;
82a1bf3f78SToomas Soome 	int sign = ((radix == 10) && (value < 0));
83a1bf3f78SToomas Soome 	int pwr;
84a1bf3f78SToomas Soome 
85a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, radix > 1);
86a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, radix < 37);
87a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, string);
88a1bf3f78SToomas Soome 
89a1bf3f78SToomas Soome 	pwr = ficlIsPowerOfTwo((ficlUnsigned)radix);
90a1bf3f78SToomas Soome 
91a1bf3f78SToomas Soome 	if (sign)
92a1bf3f78SToomas Soome 		value = -value;
93a1bf3f78SToomas Soome 
94a1bf3f78SToomas Soome 	if (value == 0)
95a1bf3f78SToomas Soome 		*cp++ = '0';
96a1bf3f78SToomas Soome 	else if (pwr != 0) {
97a1bf3f78SToomas Soome 		ficlUnsigned v = (ficlUnsigned) value;
98*608e6d66SToomas Soome 		ficlUnsigned mask = ~(ULONG_MAX << pwr);
99a1bf3f78SToomas Soome 		while (v) {
100a1bf3f78SToomas Soome 			*cp++ = digits[v & mask];
101a1bf3f78SToomas Soome 			v >>= pwr;
102a1bf3f78SToomas Soome 		}
103a1bf3f78SToomas Soome 	} else {
104a1bf3f78SToomas Soome 		ficl2UnsignedQR result;
105a1bf3f78SToomas Soome 		ficl2Unsigned v;
106a1bf3f78SToomas Soome 		FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v);
107a1bf3f78SToomas Soome 		while (FICL_2UNSIGNED_NOT_ZERO(v)) {
108a1bf3f78SToomas Soome 			result = ficl2UnsignedDivide(v, (ficlUnsigned)radix);
109a1bf3f78SToomas Soome 			*cp++ = digits[result.remainder];
110a1bf3f78SToomas Soome 			v = result.quotient;
111a1bf3f78SToomas Soome 		}
112a1bf3f78SToomas Soome 	}
113a1bf3f78SToomas Soome 
114a1bf3f78SToomas Soome 	if (sign)
115a1bf3f78SToomas Soome 		*cp++ = '-';
116a1bf3f78SToomas Soome 
117a1bf3f78SToomas Soome 	*cp++ = '\0';
118a1bf3f78SToomas Soome 
119a1bf3f78SToomas Soome 	return (ficlStringReverse(string));
120a1bf3f78SToomas Soome }
121a1bf3f78SToomas Soome 
122a1bf3f78SToomas Soome /*
123a1bf3f78SToomas Soome  * u l t o a
124a1bf3f78SToomas Soome  */
125a1bf3f78SToomas Soome char *
126a1bf3f78SToomas Soome ficlUltoa(ficlUnsigned value, char *string, int radix)
127a1bf3f78SToomas Soome {
128a1bf3f78SToomas Soome 	char *cp = string;
129a1bf3f78SToomas Soome 	ficl2Unsigned ud;
130a1bf3f78SToomas Soome 	ficl2UnsignedQR result;
131a1bf3f78SToomas Soome 
132a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, radix > 1);
133a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, radix < 37);
134a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, string);
135a1bf3f78SToomas Soome 
136a1bf3f78SToomas Soome 	if (value == 0)
137a1bf3f78SToomas Soome 		*cp++ = '0';
138a1bf3f78SToomas Soome 	else {
139a1bf3f78SToomas Soome 		FICL_UNSIGNED_TO_2UNSIGNED(value, ud);
140a1bf3f78SToomas Soome 		while (FICL_2UNSIGNED_NOT_ZERO(ud)) {
141a1bf3f78SToomas Soome 			result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix);
142a1bf3f78SToomas Soome 			ud = result.quotient;
143a1bf3f78SToomas Soome 			*cp++ = digits[result.remainder];
144a1bf3f78SToomas Soome 		}
145a1bf3f78SToomas Soome 	}
146a1bf3f78SToomas Soome 
147a1bf3f78SToomas Soome 	*cp++ = '\0';
148a1bf3f78SToomas Soome 
149a1bf3f78SToomas Soome 	return (ficlStringReverse(string));
150a1bf3f78SToomas Soome }
151a1bf3f78SToomas Soome 
152a1bf3f78SToomas Soome /*
153a1bf3f78SToomas Soome  * c a s e F o l d
154a1bf3f78SToomas Soome  * Case folds a NULL terminated string in place. All characters
155a1bf3f78SToomas Soome  * get converted to lower case.
156a1bf3f78SToomas Soome  */
157a1bf3f78SToomas Soome char *
158a1bf3f78SToomas Soome ficlStringCaseFold(char *cp)
159a1bf3f78SToomas Soome {
160a1bf3f78SToomas Soome 	char *oldCp = cp;
161a1bf3f78SToomas Soome 
162a1bf3f78SToomas Soome 	while (*cp) {
163a1bf3f78SToomas Soome 		if (isupper((unsigned char)*cp))
164a1bf3f78SToomas Soome 			*cp = (char)tolower((unsigned char)*cp);
165a1bf3f78SToomas Soome 		cp++;
166a1bf3f78SToomas Soome 	}
167a1bf3f78SToomas Soome 
168a1bf3f78SToomas Soome 	return (oldCp);
169a1bf3f78SToomas Soome }
170a1bf3f78SToomas Soome 
171a1bf3f78SToomas Soome /*
172a1bf3f78SToomas Soome  * s t r i n c m p
173a1bf3f78SToomas Soome  * (jws) simplified the code a bit in hopes of appeasing Purify
174a1bf3f78SToomas Soome  */
175a1bf3f78SToomas Soome int
176a1bf3f78SToomas Soome ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count)
177a1bf3f78SToomas Soome {
178a1bf3f78SToomas Soome 	int i = 0;
179a1bf3f78SToomas Soome 
180a1bf3f78SToomas Soome 	for (; 0 < count; ++cp1, ++cp2, --count) {
181a1bf3f78SToomas Soome 		i = tolower((unsigned char)*cp1) - tolower((unsigned char)*cp2);
182a1bf3f78SToomas Soome 		if (i != 0)
183a1bf3f78SToomas Soome 			return (i);
184a1bf3f78SToomas Soome 		else if (*cp1 == '\0')
185a1bf3f78SToomas Soome 			return (0);
186a1bf3f78SToomas Soome 	}
187a1bf3f78SToomas Soome 	return (0);
188a1bf3f78SToomas Soome }
189a1bf3f78SToomas Soome 
190a1bf3f78SToomas Soome /*
191a1bf3f78SToomas Soome  * s k i p S p a c e
192a1bf3f78SToomas Soome  * Given a string pointer, returns a pointer to the first non-space
193a1bf3f78SToomas Soome  * char of the string, or to the NULL terminator if no such char found.
194a1bf3f78SToomas Soome  * If the pointer reaches "end" first, stop there. Pass NULL to
195a1bf3f78SToomas Soome  * suppress this behavior.
196a1bf3f78SToomas Soome  */
197a1bf3f78SToomas Soome char *
198a1bf3f78SToomas Soome ficlStringSkipSpace(char *cp, char *end)
199a1bf3f78SToomas Soome {
200a1bf3f78SToomas Soome 	FICL_ASSERT(NULL, cp);
201a1bf3f78SToomas Soome 
202a1bf3f78SToomas Soome 	while ((cp != end) && isspace((unsigned char)*cp))
203a1bf3f78SToomas Soome 		cp++;
204a1bf3f78SToomas Soome 
205a1bf3f78SToomas Soome 	return (cp);
206a1bf3f78SToomas Soome }
207a1bf3f78SToomas Soome 
208a1bf3f78SToomas Soome void
209a1bf3f78SToomas Soome ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text,
210a1bf3f78SToomas Soome     ficlCompatibilityOutputFunction outputFunction)
211a1bf3f78SToomas Soome {
212a1bf3f78SToomas Soome 	char buffer[256];
213a1bf3f78SToomas Soome 	char *bufferStop = buffer + sizeof (buffer) - 1;
214a1bf3f78SToomas Soome 
215a1bf3f78SToomas Soome 	if (text == NULL) {
216a1bf3f78SToomas Soome 		outputFunction(callback->vm, NULL, 0 /* false */);
217a1bf3f78SToomas Soome 		return;
218a1bf3f78SToomas Soome 	}
219a1bf3f78SToomas Soome 
220a1bf3f78SToomas Soome 	while (*text) {
221a1bf3f78SToomas Soome 		int newline = 0 /* false */;
222a1bf3f78SToomas Soome 		char *trace = buffer;
223a1bf3f78SToomas Soome 		while ((*text) && (trace < bufferStop)) {
224a1bf3f78SToomas Soome 			switch (*text) {
225a1bf3f78SToomas Soome 			/* throw away \r */
226a1bf3f78SToomas Soome 			case '\r':
227a1bf3f78SToomas Soome 				text++;
228a1bf3f78SToomas Soome 			continue;
229a1bf3f78SToomas Soome 			case '\n':
230a1bf3f78SToomas Soome 				text++;
231a1bf3f78SToomas Soome 				newline = !0 /* true */;
232a1bf3f78SToomas Soome 			break;
233a1bf3f78SToomas Soome 			default:
234a1bf3f78SToomas Soome 				*trace++ = *text++;
235a1bf3f78SToomas Soome 			break;
236a1bf3f78SToomas Soome 			}
237a1bf3f78SToomas Soome 		}
238a1bf3f78SToomas Soome 
239a1bf3f78SToomas Soome 		*trace = 0;
240a1bf3f78SToomas Soome 		(outputFunction)(callback->vm, buffer, newline);
241a1bf3f78SToomas Soome 	}
242a1bf3f78SToomas Soome }
243