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