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