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