Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sli.c
00001 /* 00002 # This file is Copyright 2002 Dean Hall. 00003 # This file is part of the PyMite VM. 00004 # This file is licensed under the MIT License. 00005 # See the LICENSE file for details. 00006 */ 00007 00008 00009 #undef __FILE_ID__ 00010 #define __FILE_ID__ 0x11 00011 00012 00013 /** 00014 * \file 00015 * \brief Standard Library Interface 00016 * 00017 * PyMite requires a few functions from a few different 00018 * standard C libraries (memory, string, etc). 00019 */ 00020 00021 00022 #include "pm.h" 00023 00024 00025 /** use Duff's Device or simple for-loop for memcpy. */ 00026 #define USE_DUFFS_DEVICE 0 00027 00028 00029 #if !HAVE_STRING_H 00030 00031 void * 00032 sli_memcpy(unsigned char *to, unsigned char const *from, unsigned int n) 00033 { 00034 unsigned char *tobak; 00035 00036 /* Store init value of to */ 00037 tobak = to; 00038 00039 #if USE_DUFFS_DEVICE 00040 if (n > 0) 00041 { 00042 switch (n & 0x7) 00043 do 00044 { 00045 case 0: 00046 *to++ = *from++; 00047 case 7: 00048 *to++ = *from++; 00049 case 6: 00050 *to++ = *from++; 00051 case 5: 00052 *to++ = *from++; 00053 case 4: 00054 *to++ = *from++; 00055 case 3: 00056 *to++ = *from++; 00057 case 2: 00058 *to++ = *from++; 00059 case 1: 00060 *to++ = *from++; 00061 } 00062 while ((n -= 8) > 0); 00063 } 00064 #else 00065 for (; n > 0; n--) 00066 { 00067 *to = *from; 00068 from++; 00069 to++; 00070 } 00071 #endif /* USE_DUFFS_DEVICE */ 00072 return tobak; 00073 } 00074 00075 00076 int 00077 sli_strlen(char const *s) 00078 { 00079 char const *si = s; 00080 int len = 0; 00081 00082 while (*si++) 00083 { 00084 len++; 00085 } 00086 return len; 00087 } 00088 00089 00090 int 00091 sli_strcmp(char const *s1, char const *s2) 00092 { 00093 /* While not at either strings' end and they're same */ 00094 while ((*s1 != C_NULL) && (*s2 != C_NULL) && (*s1 == *s2)) 00095 { 00096 s1++; 00097 s2++; 00098 } 00099 00100 /* Return string difference */ 00101 return *s1 - *s2; 00102 } 00103 00104 00105 int 00106 sli_strncmp(char const *s1, char const *s2, unsigned int n) 00107 { 00108 unsigned int i = 0; 00109 00110 if (n == 0) 00111 { 00112 return 0; 00113 } 00114 00115 /* Scan n bytes in string */ 00116 for (i = 0; i < n; i++) 00117 { 00118 /* If bytes differ, return difference */ 00119 if (s1[i] != s2[i]) 00120 { 00121 return s1[i] - s2[i]; 00122 } 00123 } 00124 return 0; 00125 } 00126 00127 #endif /* HAVE_STRING_H */ 00128 00129 00130 /* 00131 * This function is moved outside of HAVE_STRING_H because the one in string.h 00132 * will not accept a null value for the second arg 00133 */ 00134 void 00135 sli_memset(unsigned char *dest, char const val, unsigned int n) 00136 { 00137 unsigned int i; 00138 00139 for (i = 0; i < n; i++) 00140 { 00141 *dest = (unsigned char)val; 00142 dest++; 00143 } 00144 } 00145 00146 void 00147 sli_puts(uint8_t * s) 00148 { 00149 uint8_t *ps = s; 00150 uint8_t c; 00151 00152 c = *ps; 00153 ps++; 00154 while (c != '\0') 00155 { 00156 plat_putByte(c); 00157 c = *ps; 00158 ps++; 00159 } 00160 } 00161 00162 00163 PmReturn_t 00164 sli_ltoa10(int32_t value, uint8_t *buf, uint8_t buflen) 00165 { 00166 int32_t const decimal_places[] = { 1000000000, 100000000, 10000000, 1000000, 00167 100000, 10000, 1000, 100, 10, 1 }; 00168 int32_t decimal_place; 00169 int32_t number; 00170 uint8_t c; 00171 uint8_t printed_one = C_FALSE; 00172 uint8_t i; 00173 uint8_t j; 00174 PmReturn_t retval = PM_RET_OK; 00175 00176 C_ASSERT(buflen >= 12); 00177 00178 number = value; 00179 if (number == 0) 00180 { 00181 buf[0] = '0'; 00182 buf[1] = '\0'; 00183 return retval; 00184 } 00185 00186 /* Special case (can't convert it to positive value) */ 00187 if (number == -2147483648) 00188 { 00189 sli_memcpy(buf, (unsigned char *)"-2147483648", 11); 00190 return PM_RET_OK; 00191 } 00192 00193 j = 0; 00194 if (number < 0) 00195 { 00196 buf[0] = '-'; 00197 j++; 00198 number = -number; 00199 } 00200 00201 for (i = 0; i < 10; i++) 00202 { 00203 decimal_place = decimal_places[i]; 00204 c = '0'; 00205 while (number >= decimal_place) 00206 { 00207 number -= decimal_place; 00208 c++; 00209 } 00210 if ((c != '0') || printed_one) 00211 { 00212 buf[j++] = c; 00213 printed_one = C_TRUE; 00214 } 00215 } 00216 buf[j] = '\0'; 00217 00218 return retval; 00219 } 00220 00221 char const * const hexChars = "0123456789abcdef"; 00222 00223 /* MUST show leading zeros because callers don't keep track */ 00224 PmReturn_t 00225 sli_btoa16(uint8_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) 00226 { 00227 C_ASSERT(buflen >= 3); 00228 00229 if (upperCase) upperCase = 'A' - 'a'; 00230 00231 buf[0] = (value >> 4) > 9 00232 ? hexChars[value >> 4] + upperCase 00233 : hexChars[value >> 4]; 00234 buf[1] = (value & 0x0F) > 9 00235 ? hexChars[value & 0x0F] + upperCase 00236 : hexChars[value & 0x0F]; 00237 buf[2] = '\0'; 00238 00239 return PM_RET_OK; 00240 } 00241 00242 00243 /* Does NOT show leading zeroes */ 00244 PmReturn_t 00245 sli_ltoa16(int32_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) 00246 { 00247 int8_t i; 00248 uint8_t j = 0; 00249 uint8_t showZero = C_FALSE; 00250 uint8_t nibble; 00251 00252 C_ASSERT(buflen >= 9); 00253 00254 if (upperCase) upperCase = 'A' - 'a'; 00255 00256 for (i = 28; i >= 0; i -= 4) 00257 { 00258 nibble = ((value >> i) & 0xF); 00259 if ((nibble == 0) && !showZero) continue; 00260 buf[j++] = (nibble > 9) 00261 ? hexChars[nibble] + upperCase 00262 : hexChars[nibble]; 00263 showZero = C_TRUE; 00264 } 00265 buf[j] = '\0'; 00266 00267 return PM_RET_OK; 00268 } 00269 00270 00271 PmReturn_t 00272 sli_ptoa16(intptr_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) 00273 { 00274 PmReturn_t retval; 00275 int8_t i; 00276 int8_t j; 00277 00278 C_ASSERT(buflen >= 2 * sizeof(intptr_t) + 1); 00279 00280 /* Print the hex value, most significant byte first */ 00281 for (j = 0, i = 8 * sizeof(intptr_t) - 8; i >= 0; i -= 8, j += 2) 00282 { 00283 retval = sli_btoa16((value >> i) & 0xFF, &buf[j], buflen - j, upperCase); 00284 PM_BREAK_IF_ERROR(retval); 00285 } 00286 00287 return retval; 00288 } 00289 00290 00291 typedef union { 00292 int32_t L; 00293 float F; 00294 } LF_t; 00295 00296 00297 /* The buf MUST be at least 15 bytes long */ 00298 PmReturn_t 00299 sli_ftoa(float f, uint8_t *buf, uint8_t buflen) 00300 { 00301 uint32_t mantissa, int_part, frac_part; 00302 int16_t exp2; 00303 LF_t x; 00304 uint8_t *p; 00305 int8_t adj = 0; 00306 PmReturn_t retval = PM_RET_OK; 00307 00308 C_ASSERT(buflen >= 15); 00309 00310 if (f == 0.0) 00311 { 00312 buf[0] = '0'; 00313 buf[1] = '.'; 00314 buf[2] = '0'; 00315 buf[3] = '\0'; 00316 return PM_RET_OK; 00317 } 00318 x.F = f; 00319 00320 exp2 = (0xFF & (x.L >> 23)) - 127; 00321 mantissa = (x.L & 0xFFFFFF) | 0x800000; 00322 frac_part = 0; 00323 int_part = 0; 00324 p = buf; 00325 00326 /* Adjust large exponents using the approximation: 2**10 == k*10**3 */ 00327 while (exp2 >= 31) 00328 { 00329 /* Reduce the binary exponent here (incr the decimal exponent below) */ 00330 exp2 -= 10; 00331 adj++; 00332 00333 /* 00334 * To use the approximation above, the mantissa must be multiplied by k 00335 * where k = 1.024 ~= (1 + 12583/(2**19)) 00336 * Divide first to avoid integer overflow (the mantissa is 24 bits) 00337 */ 00338 mantissa += ((mantissa >> 6) * 12583) >> 13; 00339 } 00340 00341 if (exp2 < -23) 00342 { 00343 // Unable to handle large negative exponents at this time 00344 *p++ = '?'; 00345 return PM_RET_OK; 00346 } 00347 else if (exp2 >= 23) 00348 { 00349 int_part = mantissa << (exp2 - 23); 00350 } 00351 else if (exp2 >= 0) 00352 { 00353 int_part = mantissa >> (23 - exp2); 00354 frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF; 00355 } 00356 else /* if (exp2 < 0) */ 00357 { 00358 frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1); 00359 } 00360 00361 if (x.L < 0) 00362 { 00363 *p++ = '-'; 00364 } 00365 00366 if (int_part == 0) 00367 { 00368 *p++ = '0'; 00369 } 00370 else 00371 { 00372 retval = sli_ltoa10(int_part, p, buflen - (p - buf)); 00373 PM_RETURN_IF_ERROR(retval); 00374 while (*p) p++; 00375 } 00376 *p++ = '.'; 00377 00378 if (frac_part == 0) 00379 { 00380 *p++ = '0'; 00381 } 00382 else 00383 { 00384 char m, max; 00385 00386 max = buflen - (p - buf) - 1; 00387 if (max > 6) 00388 { 00389 max = 6; 00390 } 00391 00392 /* Print fractional part */ 00393 for (m = 0; m < max; m++) 00394 { 00395 frac_part *= 10; 00396 *p++ = '0' + (frac_part >> 24); 00397 frac_part &= 0xFFFFFF; 00398 } 00399 00400 /* Remove ending zeroes */ 00401 //for (--p; p[0] == '0' && p[-1] != '.'; --p); 00402 //++p; 00403 } 00404 00405 /* 00406 * If the exponent is large (adjustment took place above), 00407 * normalize the string to scientific notation 00408 */ 00409 if (adj != 0) 00410 { 00411 uint8_t i; 00412 00413 /* Shift chars to make room for the new decimal point */ 00414 i = (p - buf + 1); 00415 i = (i > (buflen - 1)) ? buflen - 1 : i; 00416 for (; i > 1; i--) 00417 { 00418 buf[i] = buf[i-1]; 00419 } 00420 00421 /* Find the index of the old decimal point */ 00422 for (i = 6; (buf[i] != '.') && (i < 15); i++); 00423 00424 /* Set the new decimal point (normalized) */ 00425 buf[1] = '.'; 00426 00427 /* 00428 * Adjust the decimal exponent (3 decimal places for every 10 bits) 00429 * and add the amount for the normalization 00430 */ 00431 p = &buf[8]; 00432 *p++ = 'e'; 00433 *p++ = '+'; 00434 retval = sli_ltoa10(3 * adj + (i - 2), p, buflen - (p - buf)); 00435 PM_RETURN_IF_ERROR(retval); 00436 while (*p) p++; 00437 } 00438 00439 *p = '\0'; 00440 00441 return PM_RET_OK; 00442 }
Generated on Tue Jul 12 2022 23:13:47 by
1.7.2