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 * 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 * 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 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 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 * 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 * 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 * 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 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 * 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 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