summaryrefslogtreecommitdiff
path: root/utility.c
diff options
context:
space:
mode:
Diffstat (limited to 'utility.c')
-rw-r--r--utility.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/utility.c b/utility.c
new file mode 100644
index 000000000000..0a9d2a0c7487
--- /dev/null
+++ b/utility.c
@@ -0,0 +1,262 @@
+#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);
+ }
+}