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