1 #include "ficl.h" 2 3 /* 4 * a l i g n P t r 5 * Aligns the given pointer to FICL_ALIGN address units. 6 * Returns the aligned pointer value. 7 */ 8 void * 9 ficlAlignPointer(void *ptr) 10 { 11 #if FICL_PLATFORM_ALIGNMENT > 1 12 intptr_t p = (intptr_t)ptr; 13 14 if (p & (FICL_PLATFORM_ALIGNMENT - 1)) 15 ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) + 16 FICL_PLATFORM_ALIGNMENT); 17 #endif 18 return (ptr); 19 } 20 21 /* 22 * s t r r e v 23 */ 24 char * 25 ficlStringReverse(char *string) 26 { 27 int i = strlen(string); 28 char *p1 = string; /* first char of string */ 29 char *p2 = string + i - 1; /* last non-NULL char of string */ 30 char c; 31 32 if (i > 1) { 33 while (p1 < p2) { 34 c = *p2; 35 *p2 = *p1; 36 *p1 = c; 37 p1++; p2--; 38 } 39 } 40 41 return (string); 42 } 43 44 /* 45 * d i g i t _ t o _ c h a r 46 */ 47 static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 48 49 char 50 ficlDigitToCharacter(int value) 51 { 52 return (digits[value]); 53 } 54 55 /* 56 * i s P o w e r O f T w o 57 * Tests whether supplied argument is an integer power of 2 (2**n) 58 * where 32 > n > 1, and returns n if so. Otherwise returns zero. 59 */ 60 int 61 ficlIsPowerOfTwo(ficlUnsigned u) 62 { 63 int i = 1; 64 ficlUnsigned t = 2; 65 66 for (; ((t <= u) && (t != 0)); i++, t <<= 1) { 67 if (u == t) 68 return (i); 69 } 70 71 return (0); 72 } 73 74 /* 75 * l t o a 76 */ 77 char * 78 ficlLtoa(ficlInteger value, char *string, int radix) 79 { 80 char *cp = string; 81 int sign = ((radix == 10) && (value < 0)); 82 int pwr; 83 84 FICL_ASSERT(NULL, radix > 1); 85 FICL_ASSERT(NULL, radix < 37); 86 FICL_ASSERT(NULL, string); 87 88 pwr = ficlIsPowerOfTwo((ficlUnsigned)radix); 89 90 if (sign) 91 value = -value; 92 93 if (value == 0) 94 *cp++ = '0'; 95 else if (pwr != 0) { 96 ficlUnsigned v = (ficlUnsigned) value; 97 ficlUnsigned mask = (ficlUnsigned) ~(-1 << pwr); 98 while (v) { 99 *cp++ = digits[v & mask]; 100 v >>= pwr; 101 } 102 } else { 103 ficl2UnsignedQR result; 104 ficl2Unsigned v; 105 FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v); 106 while (FICL_2UNSIGNED_NOT_ZERO(v)) { 107 result = ficl2UnsignedDivide(v, (ficlUnsigned)radix); 108 *cp++ = digits[result.remainder]; 109 v = result.quotient; 110 } 111 } 112 113 if (sign) 114 *cp++ = '-'; 115 116 *cp++ = '\0'; 117 118 return (ficlStringReverse(string)); 119 } 120 121 /* 122 * u l t o a 123 */ 124 char * 125 ficlUltoa(ficlUnsigned value, char *string, int radix) 126 { 127 char *cp = string; 128 ficl2Unsigned ud; 129 ficl2UnsignedQR result; 130 131 FICL_ASSERT(NULL, radix > 1); 132 FICL_ASSERT(NULL, radix < 37); 133 FICL_ASSERT(NULL, string); 134 135 if (value == 0) 136 *cp++ = '0'; 137 else { 138 FICL_UNSIGNED_TO_2UNSIGNED(value, ud); 139 while (FICL_2UNSIGNED_NOT_ZERO(ud)) { 140 result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix); 141 ud = result.quotient; 142 *cp++ = digits[result.remainder]; 143 } 144 } 145 146 *cp++ = '\0'; 147 148 return (ficlStringReverse(string)); 149 } 150 151 /* 152 * c a s e F o l d 153 * Case folds a NULL terminated string in place. All characters 154 * get converted to lower case. 155 */ 156 char * 157 ficlStringCaseFold(char *cp) 158 { 159 char *oldCp = cp; 160 161 while (*cp) { 162 if (isupper((unsigned char)*cp)) 163 *cp = (char)tolower((unsigned char)*cp); 164 cp++; 165 } 166 167 return (oldCp); 168 } 169 170 /* 171 * s t r i n c m p 172 * (jws) simplified the code a bit in hopes of appeasing Purify 173 */ 174 int 175 ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count) 176 { 177 int i = 0; 178 179 for (; 0 < count; ++cp1, ++cp2, --count) { 180 i = tolower((unsigned char)*cp1) - tolower((unsigned char)*cp2); 181 if (i != 0) 182 return (i); 183 else if (*cp1 == '\0') 184 return (0); 185 } 186 return (0); 187 } 188 189 /* 190 * s k i p S p a c e 191 * Given a string pointer, returns a pointer to the first non-space 192 * char of the string, or to the NULL terminator if no such char found. 193 * If the pointer reaches "end" first, stop there. Pass NULL to 194 * suppress this behavior. 195 */ 196 char * 197 ficlStringSkipSpace(char *cp, char *end) 198 { 199 FICL_ASSERT(NULL, cp); 200 201 while ((cp != end) && isspace((unsigned char)*cp)) 202 cp++; 203 204 return (cp); 205 } 206 207 void 208 ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text, 209 ficlCompatibilityOutputFunction outputFunction) 210 { 211 char buffer[256]; 212 char *bufferStop = buffer + sizeof (buffer) - 1; 213 214 if (text == NULL) { 215 outputFunction(callback->vm, NULL, 0 /* false */); 216 return; 217 } 218 219 while (*text) { 220 int newline = 0 /* false */; 221 char *trace = buffer; 222 while ((*text) && (trace < bufferStop)) { 223 switch (*text) { 224 /* throw away \r */ 225 case '\r': 226 text++; 227 continue; 228 case '\n': 229 text++; 230 newline = !0 /* true */; 231 break; 232 default: 233 *trace++ = *text++; 234 break; 235 } 236 } 237 238 *trace = 0; 239 (outputFunction)(callback->vm, buffer, newline); 240 } 241 } 242