hdo
beta
|
00001 /* ---------------------------------------------------------------------------- 00002 * ATMEL Microcontroller Software Support 00003 * ---------------------------------------------------------------------------- 00004 * Copyright (c) 2008, Atmel Corporation 00005 * 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * 00011 * - Redistributions of source code must retain the above copyright notice, 00012 * this list of conditions and the disclaimer below. 00013 * 00014 * Atmel's name may not be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR 00018 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00019 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 00020 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, 00021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 00023 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00024 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00025 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00026 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 * ---------------------------------------------------------------------------- 00028 */ 00029 00030 //------------------------------------------------------------------------------ 00043 //------------------------------------------------------------------------------ 00044 00045 //------------------------------------------------------------------------------ 00046 // Headers 00047 //------------------------------------------------------------------------------ 00048 00049 #include <stdio.h> 00050 #include <stdarg.h> 00051 00052 //------------------------------------------------------------------------------ 00053 // Local Definitions 00054 //------------------------------------------------------------------------------ 00055 00056 // Maximum string size allowed (in bytes). 00057 #define MAX_STRING_SIZE 100 00058 00059 //------------------------------------------------------------------------------ 00060 // Global Variables 00061 //------------------------------------------------------------------------------ 00062 00063 // Required for proper compilation. 00064 struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0}; 00065 struct _reent *_impure_ptr = &r; 00066 00067 //------------------------------------------------------------------------------ 00068 // Local Functions 00069 //------------------------------------------------------------------------------ 00070 00071 //------------------------------------------------------------------------------ 00072 // Writes a character inside the given string. Returns 1. 00073 // \param pStr Storage string. 00074 // \param c Character to write. 00075 //------------------------------------------------------------------------------ 00076 signed int PutChar(char *pStr, char c) 00077 { 00078 *pStr = c; 00079 return 1; 00080 } 00081 00082 //------------------------------------------------------------------------------ 00083 // Writes a string inside the given string. 00084 // Returns the size of the written 00085 // string. 00086 // \param pStr Storage string. 00087 // \param pSource Source string. 00088 //------------------------------------------------------------------------------ 00089 signed int PutString(char *pStr, const char *pSource) 00090 { 00091 signed int num = 0; 00092 00093 while (*pSource != 0) { 00094 00095 *pStr++ = *pSource++; 00096 num++; 00097 } 00098 00099 return num; 00100 } 00101 00102 //------------------------------------------------------------------------------ 00103 // Writes an unsigned int inside the given string, using the provided fill & 00104 // width parameters. 00105 // Returns the size in characters of the written integer. 00106 // \param pStr Storage string. 00107 // \param fill Fill character. 00108 // \param width Minimum integer width. 00109 // \param value Integer value. 00110 //------------------------------------------------------------------------------ 00111 signed int PutUnsignedInt( 00112 char *pStr, 00113 char fill, 00114 signed int width, 00115 unsigned int value) 00116 { 00117 signed int num = 0; 00118 00119 // Take current digit into account when calculating width 00120 width--; 00121 00122 // Recursively write upper digits 00123 if ((value / 10) > 0) { 00124 00125 num = PutUnsignedInt(pStr, fill, width, value / 10); 00126 pStr += num; 00127 } 00128 // Write filler characters 00129 else { 00130 00131 while (width > 0) { 00132 00133 PutChar(pStr, fill); 00134 pStr++; 00135 num++; 00136 width--; 00137 } 00138 } 00139 00140 // Write lower digit 00141 num += PutChar(pStr, (value % 10) + '0'); 00142 00143 return num; 00144 } 00145 00146 //------------------------------------------------------------------------------ 00147 // Writes a signed int inside the given string, using the provided fill & width 00148 // parameters. 00149 // Returns the size of the written integer. 00150 // \param pStr Storage string. 00151 // \param fill Fill character. 00152 // \param width Minimum integer width. 00153 // \param value Signed integer value. 00154 //------------------------------------------------------------------------------ 00155 signed int PutSignedInt( 00156 char *pStr, 00157 char fill, 00158 signed int width, 00159 signed int value) 00160 { 00161 signed int num = 0; 00162 unsigned int absolute; 00163 00164 // Compute absolute value 00165 if (value < 0) { 00166 00167 absolute = -value; 00168 } 00169 else { 00170 00171 absolute = value; 00172 } 00173 00174 // Take current digit into account when calculating width 00175 width--; 00176 00177 // Recursively write upper digits 00178 if ((absolute / 10) > 0) { 00179 00180 if (value < 0) { 00181 00182 num = PutSignedInt(pStr, fill, width, -(absolute / 10)); 00183 } 00184 else { 00185 00186 num = PutSignedInt(pStr, fill, width, absolute / 10); 00187 } 00188 pStr += num; 00189 } 00190 else { 00191 00192 // Reserve space for sign 00193 if (value < 0) { 00194 00195 width--; 00196 } 00197 00198 // Write filler characters 00199 while (width > 0) { 00200 00201 PutChar(pStr, fill); 00202 pStr++; 00203 num++; 00204 width--; 00205 } 00206 00207 // Write sign 00208 if (value < 0) { 00209 00210 num += PutChar(pStr, '-'); 00211 pStr++; 00212 } 00213 } 00214 00215 // Write lower digit 00216 num += PutChar(pStr, (absolute % 10) + '0'); 00217 00218 return num; 00219 } 00220 00221 //------------------------------------------------------------------------------ 00222 // Writes an hexadecimal value into a string, using the given fill, width & 00223 // capital parameters. 00224 // Returns the number of char written. 00225 // \param pStr Storage string. 00226 // \param fill Fill character. 00227 // \param width Minimum integer width. 00228 // \param maj Indicates if the letters must be printed in lower- or upper-case. 00229 // \param value Hexadecimal value. 00230 //------------------------------------------------------------------------------ 00231 signed int PutHexa( 00232 char *pStr, 00233 char fill, 00234 signed int width, 00235 unsigned char maj, 00236 unsigned int value) 00237 { 00238 signed int num = 0; 00239 00240 // Decrement width 00241 width--; 00242 00243 // Recursively output upper digits 00244 if ((value >> 4) > 0) { 00245 00246 num += PutHexa(pStr, fill, width, maj, value >> 4); 00247 pStr += num; 00248 } 00249 // Write filler chars 00250 else { 00251 00252 while (width > 0) { 00253 00254 PutChar(pStr, fill); 00255 pStr++; 00256 num++; 00257 width--; 00258 } 00259 } 00260 00261 // Write current digit 00262 if ((value & 0xF) < 10) { 00263 00264 PutChar(pStr, (value & 0xF) + '0'); 00265 } 00266 else if (maj) { 00267 00268 PutChar(pStr, (value & 0xF) - 10 + 'A'); 00269 } 00270 else { 00271 00272 PutChar(pStr, (value & 0xF) - 10 + 'a'); 00273 } 00274 num++; 00275 00276 return num; 00277 } 00278 00279 //------------------------------------------------------------------------------ 00280 // Global Functions 00281 //------------------------------------------------------------------------------ 00282 00283 //------------------------------------------------------------------------------ 00291 //------------------------------------------------------------------------------ 00292 signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap) 00293 { 00294 char fill; 00295 unsigned char width; 00296 signed int num = 0; 00297 signed int size = 0; 00298 00299 // Clear the string 00300 if (pStr) { 00301 00302 *pStr = 0; 00303 } 00304 00305 // Phase string 00306 while (*pFormat != 0 && size < length) { 00307 00308 // Normal character 00309 if (*pFormat != '%') { 00310 00311 *pStr++ = *pFormat++; 00312 size++; 00313 } 00314 // Escaped '%' 00315 else if (*(pFormat+1) == '%') { 00316 00317 *pStr++ = '%'; 00318 pFormat += 2; 00319 size++; 00320 } 00321 // Token delimiter 00322 else { 00323 00324 fill = ' '; 00325 width = 0; 00326 pFormat++; 00327 00328 // Parse filler 00329 if (*pFormat == '0') { 00330 00331 fill = '0'; 00332 pFormat++; 00333 } 00334 00335 // Parse width 00336 while ((*pFormat >= '0') && (*pFormat <= '9')) { 00337 00338 width = (width*10) + *pFormat-'0'; 00339 pFormat++; 00340 } 00341 00342 // Check if there is enough space 00343 if (size + width > length) { 00344 00345 width = length - size; 00346 } 00347 00348 // Parse type 00349 switch (*pFormat) { 00350 case 'd': 00351 case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break; 00352 case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break; 00353 case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break; 00354 case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break; 00355 case 's': num = PutString(pStr, va_arg(ap, char *)); break; 00356 case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break; 00357 default: 00358 return EOF; 00359 } 00360 00361 pFormat++; 00362 pStr += num; 00363 size += num; 00364 } 00365 } 00366 00367 // NULL-terminated (final \0 is not counted) 00368 if (size < length) { 00369 00370 *pStr = 0; 00371 } 00372 else { 00373 00374 *(--pStr) = 0; 00375 size--; 00376 } 00377 00378 return size; 00379 } 00380 00381 //------------------------------------------------------------------------------ 00389 //------------------------------------------------------------------------------ 00390 signed int snprintf(char *pString, size_t length, const char *pFormat, ...) 00391 { 00392 va_list ap; 00393 signed int rc; 00394 00395 va_start(ap, pFormat); 00396 rc = vsnprintf(pString, length, pFormat, ap); 00397 va_end(ap); 00398 00399 return rc; 00400 } 00401 00402 //------------------------------------------------------------------------------ 00409 //------------------------------------------------------------------------------ 00410 signed int vsprintf(char *pString, const char *pFormat, va_list ap) 00411 { 00412 return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap); 00413 } 00414 00415 //------------------------------------------------------------------------------ 00421 //------------------------------------------------------------------------------ 00422 signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap) 00423 { 00424 char pStr[MAX_STRING_SIZE]; 00425 char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r"; 00426 00427 // Write formatted string in buffer 00428 if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) { 00429 00430 fputs(pError, stderr); 00431 while (1); // Increase MAX_STRING_SIZE 00432 } 00433 00434 // Display string 00435 return fputs(pStr, pStream); 00436 } 00437 00438 //------------------------------------------------------------------------------ 00443 //------------------------------------------------------------------------------ 00444 signed int vprintf(const char *pFormat, va_list ap) 00445 { 00446 return vfprintf(stdout, pFormat, ap); 00447 } 00448 00449 //------------------------------------------------------------------------------ 00454 //------------------------------------------------------------------------------ 00455 signed int fprintf(FILE *pStream, const char *pFormat, ...) 00456 { 00457 va_list ap; 00458 signed int result; 00459 00460 // Forward call to vfprintf 00461 va_start(ap, pFormat); 00462 result = vfprintf(pStream, pFormat, ap); 00463 va_end(ap); 00464 00465 return result; 00466 } 00467 00468 //------------------------------------------------------------------------------ 00472 //------------------------------------------------------------------------------ 00473 signed int printf(const char *pFormat, ...) 00474 { 00475 va_list ap; 00476 signed int result; 00477 00478 // Forward call to vprintf 00479 va_start(ap, pFormat); 00480 result = vprintf(pFormat, ap); 00481 va_end(ap); 00482 00483 return result; 00484 } 00485 00486 //------------------------------------------------------------------------------ 00490 //------------------------------------------------------------------------------ 00491 signed int sprintf(char *pStr, const char *pFormat, ...) 00492 { 00493 va_list ap; 00494 signed int result; 00495 00496 // Forward call to vsprintf 00497 va_start(ap, pFormat); 00498 result = vsprintf(pStr, pFormat, ap); 00499 va_end(ap); 00500 00501 return result; 00502 } 00503 00504 //------------------------------------------------------------------------------ 00507 //------------------------------------------------------------------------------ 00508 signed int puts(const char *pStr) 00509 { 00510 return fputs(pStr, stdout); 00511 } 00512