ref: 7d02e382d314d5bdde7978ccb7a64ea9201d03db
dir: /utility.c/
#include <ctype.h> #include "ficl.h" /************************************************************************** a l i g n P t r ** Aligns the given pointer to FICL_ALIGN address units. ** Returns the aligned pointer value. **************************************************************************/ void *ficlAlignPointer(void *ptr) { #if FICL_PLATFORM_ALIGNMENT > 1 intptr_t p = (intptr_t)ptr; if (p & (FICL_PLATFORM_ALIGNMENT - 1)) ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) + FICL_PLATFORM_ALIGNMENT); #endif return ptr; } /************************************************************************** s t r r e v ** **************************************************************************/ char *ficlStringReverse( char *string ) { /* reverse a string in-place */ int i = strlen(string); char *p1 = string; /* first char of string */ char *p2 = string + i - 1; /* last non-NULL char of string */ char c; if (i > 1) { while (p1 < p2) { c = *p2; *p2 = *p1; *p1 = c; p1++; p2--; } } return string; } /************************************************************************** d i g i t _ t o _ c h a r ** **************************************************************************/ static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char ficlDigitToCharacter(int value) { return digits[value]; } /************************************************************************** i s P o w e r O f T w o ** Tests whether supplied argument is an integer power of 2 (2**n) ** where 32 > n > 1, and returns n if so. Otherwise returns zero. **************************************************************************/ int ficlIsPowerOfTwo(ficlUnsigned u) { int i = 1; ficlUnsigned t = 2; for (; ((t <= u) && (t != 0)); i++, t <<= 1) { if (u == t) return i; } return 0; } /************************************************************************** l t o a ** **************************************************************************/ char *ficlLtoa( ficlInteger value, char *string, int radix ) { /* convert long to string, any base */ char *cp = string; int sign = ((radix == 10) && (value < 0)); int pwr; FICL_ASSERT(NULL, radix > 1); FICL_ASSERT(NULL, radix < 37); FICL_ASSERT(NULL, string); pwr = ficlIsPowerOfTwo((ficlUnsigned)radix); if (sign) value = -value; if (value == 0) *cp++ = '0'; else if (pwr != 0) { ficlUnsigned v = (ficlUnsigned) value; ficlUnsigned mask = (ficlUnsigned) ~(-1 << pwr); while (v) { *cp++ = digits[v & mask]; v >>= pwr; } } else { ficl2UnsignedQR result; ficl2Unsigned v; FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v); while (FICL_2UNSIGNED_NOT_ZERO(v)) { result = ficl2UnsignedDivide(v, (ficlUnsigned)radix); *cp++ = digits[result.remainder]; v = result.quotient; } } if (sign) *cp++ = '-'; *cp++ = '\0'; return ficlStringReverse(string); } /************************************************************************** u l t o a ** **************************************************************************/ char *ficlUltoa(ficlUnsigned value, char *string, int radix ) { /* convert long to string, any base */ char *cp = string; ficl2Unsigned ud; ficl2UnsignedQR result; FICL_ASSERT(NULL, radix > 1); FICL_ASSERT(NULL, radix < 37); FICL_ASSERT(NULL, string); if (value == 0) *cp++ = '0'; else { FICL_UNSIGNED_TO_2UNSIGNED(value, ud); while (FICL_2UNSIGNED_NOT_ZERO(ud)) { result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix); ud = result.quotient; *cp++ = digits[result.remainder]; } } *cp++ = '\0'; return ficlStringReverse(string); } /************************************************************************** c a s e F o l d ** Case folds a NULL terminated string in place. All characters ** get converted to lower case. **************************************************************************/ char *ficlStringCaseFold(char *cp) { char *oldCp = cp; while (*cp) { if (isupper((unsigned char)*cp)) *cp = (char)tolower((unsigned char)*cp); cp++; } return oldCp; } /************************************************************************** s t r i n c m p ** (jws) simplified the code a bit in hopes of appeasing Purify **************************************************************************/ int ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count) { int i = 0; for (; 0 < count; ++cp1, ++cp2, --count) { i = tolower((unsigned char)*cp1) - tolower((unsigned char)*cp2); if (i != 0) return i; else if (*cp1 == '\0') return 0; } return 0; } /************************************************************************** s k i p S p a c e ** Given a string pointer, returns a pointer to the first non-space ** char of the string, or to the NULL terminator if no such char found. ** If the pointer reaches "end" first, stop there. Pass NULL to ** suppress this behavior. **************************************************************************/ char *ficlStringSkipSpace(char *cp, char *end) { FICL_ASSERT(NULL, cp); while ((cp != end) && isspace((unsigned char)*cp)) cp++; return cp; } void ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text, ficlCompatibilityOutputFunction outputFunction) { char buffer[256]; char *bufferStop = buffer + sizeof(buffer) - 1; if (text == NULL) { outputFunction(callback->vm, NULL, 0 /* false */); return; } while (*text) { int newline = 0 /* false */; char *trace = buffer; while ((*text) && (trace < bufferStop)) { switch (*text) { /* throw away \r */ case '\r': text++; continue; case '\n': text++; newline = !0 /* true */; break; default: *trace++ = *text++; break; } } *trace = 0; (outputFunction)(callback->vm, buffer, newline); } }