#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)
{
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)
{
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)
{
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);
}
}