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 *
ficlAlignPointer(void * ptr)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 *
ficlStringReverse(char * string)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
ficlDigitToCharacter(int value)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
ficlIsPowerOfTwo(ficlUnsigned u)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 *
ficlLtoa(ficlInteger value,char * string,int radix)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 *
ficlUltoa(ficlUnsigned value,char * string,int radix)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 *
ficlStringCaseFold(char * cp)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
ficlStrincmp(char * cp1,char * cp2,ficlUnsigned count)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 *
ficlStringSkipSpace(char * cp,char * end)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
ficlCompatibilityTextOutCallback(ficlCallback * callback,char * text,ficlCompatibilityOutputFunction outputFunction)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