Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors 00003 * to the MC1322x project (http://mc1322x.devl.org) 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 3. Neither the name of the Institute nor the names of its contributors 00015 * may be used to endorse or promote products derived from this software 00016 * without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00019 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00022 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00023 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00024 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00025 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00026 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00027 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * This file is part of libmc1322x: see http://mc1322x.devl.org 00031 * for details. 00032 * 00033 * 00034 */ 00035 00036 /** 00037 * \file printf-stdarg.c 00038 * 00039 * \brief sprintf functions to replace newlib for AVR32 UC3. 00040 * 00041 * \author $Author: umanzoli $ 00042 * 00043 * Created on : 17-mar-2009 00044 * 00045 * 00046 */ 00047 00048 /* 00049 * Copyright 2001, 2002 Georges Menie (www.menie.org) 00050 * stdarg version contributed by Christian Ettinger 00051 * 00052 * This program is free software; you can redistribute it and/or modify 00053 * it under the terms of the GNU Lesser General Public License as published by 00054 * the Free Software Foundation; either version 2 of the License, or 00055 * (at your option) any later version. 00056 * 00057 * This program is distributed in the hope that it will be useful, 00058 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00059 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00060 * GNU Lesser General Public License for more details. 00061 * 00062 * You should have received a copy of the GNU Lesser General Public License 00063 * along with this program; if not, write to the Free Software 00064 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00065 */ 00066 00067 00068 #include <stdarg.h> 00069 #include <stdbool.h> 00070 #include <string.h> 00071 00072 #include <mc1322x.h> 00073 #include <stdint.h> 00074 00075 #define __putc(x) uart1_putc(x) 00076 00077 /** 00078 * Structure to hold data to be passed to print function with format. 00079 * Aka print context. 00080 */ 00081 struct __print_ctx_t 00082 { 00083 //! pointer to next char to be filled. 00084 char* _ptr; 00085 //! maximum length of the buffer. 00086 size_t _max_len; 00087 }; 00088 typedef struct __print_ctx_t _print_ctx_t; 00089 00090 /** 00091 * Pad string to right 00092 */ 00093 #define _PRINTFMT_PAD_RIGHT 1 00094 00095 /** 00096 * Pad the number with zeroes 00097 */ 00098 #define _PRINTFMT_PAD_ZERO 2 00099 00100 /** 00101 * The following should be enough for 32 bit int 00102 */ 00103 #define _PRINTFMT_INT_BUF_LEN 12 00104 00105 /** 00106 * Print a character to stdout (if string is null) 00107 * otherwise, put the character at the end of the provided string. 00108 */ 00109 static void __print_char( _print_ctx_t* ctx, char c ) 00110 { 00111 if( ctx ) { 00112 if( c == '\r' || c == '\n' ) { 00113 if( ctx->_max_len > 1 ) { 00114 *(ctx->_ptr)='\r'; 00115 ctx->_max_len--; 00116 ctx->_ptr++; 00117 *(ctx->_ptr)='\n'; 00118 ctx->_max_len--; 00119 ctx->_ptr++; 00120 } else { 00121 *(ctx->_ptr)='\n'; 00122 ctx->_max_len--; 00123 ctx->_ptr++; 00124 } 00125 } else { 00126 if( ctx->_max_len ) { 00127 *(ctx->_ptr)=c; 00128 ctx->_max_len--; 00129 ctx->_ptr++; 00130 } 00131 } 00132 } else { 00133 __putc( (uint8_t)c ); 00134 } 00135 } 00136 00137 /** 00138 * Print a string to a given string. 00139 */ 00140 static int __print_str( _print_ctx_t* ctx, 00141 const char *string, 00142 int width, 00143 int pad, 00144 int print_limit, 00145 bool is_number ) 00146 { 00147 int pc = 0; 00148 int padchar = ' '; 00149 int i, len; 00150 00151 if( width > 0 ) { 00152 register int len = 0; 00153 register const char *ptr; 00154 for( ptr = string; *ptr; ++ptr ) 00155 ++len; 00156 if( len >= width ) 00157 width = 0; 00158 else 00159 width -= len; 00160 if( pad & _PRINTFMT_PAD_ZERO ) 00161 padchar = '0'; 00162 } 00163 if( !( pad & _PRINTFMT_PAD_RIGHT ) ) { 00164 for( ; width > 0; --width ) { 00165 __print_char( ctx, padchar ); 00166 ++pc; 00167 } 00168 } 00169 00170 // The string to print is not the result of a number conversion to ascii. 00171 if( false == is_number ) { 00172 // For a string, printlimit is the max number of characters to display. 00173 for( ; print_limit && *string; ++string, --print_limit ) { 00174 __print_char( ctx, *string ); 00175 ++pc; 00176 } 00177 } 00178 00179 // The string to print represents an integer number. 00180 if( true == is_number ) { 00181 // In this case, printlimit is the min number of digits to print. 00182 00183 // If the length of the number to print is less than the min nb of i 00184 // digits to display, we add 0 before printing the number. 00185 len = strlen( string ); 00186 if( len < print_limit ) { 00187 i = print_limit - len; 00188 for( ; i; i-- ) { 00189 __print_char( ctx, '0' ); 00190 ++pc; 00191 } 00192 } 00193 } 00194 00195 /* 00196 * Else: The string to print is not the result of a number conversion to ascii. 00197 * For a string, printlimit is the max number of characters to display. 00198 */ 00199 for( ; print_limit && *string; ++string, --print_limit ) { 00200 __print_char( ctx, *string ); 00201 ++pc; 00202 } 00203 00204 for( ; width > 0; --width ) { 00205 __print_char( ctx, padchar ); 00206 ++pc; 00207 } 00208 00209 return pc; 00210 } 00211 00212 /** 00213 * Print a number to the given string, with the given base. 00214 */ 00215 static int __print_int( _print_ctx_t* ctx, 00216 int i, 00217 int b, 00218 int sg, 00219 int width, 00220 int pad, 00221 int letbase, 00222 int print_limit ) 00223 { 00224 char print_buf[_PRINTFMT_INT_BUF_LEN]; 00225 register char *s; 00226 register int t, neg = 0, pc = 0; 00227 register unsigned int u = i; 00228 00229 if( i == 0 ) { 00230 print_buf[0] = '0'; 00231 print_buf[1] = '\0'; 00232 return __print_str( ctx, print_buf, width, pad, print_limit, true ); 00233 } 00234 00235 if( sg && b == 10 && i < 0 ) { 00236 neg = 1; 00237 u = -i; 00238 } 00239 00240 s = print_buf + _PRINTFMT_INT_BUF_LEN - 1; 00241 *s = '\0'; 00242 00243 while( u ) { 00244 t = u % b; 00245 if( t >= 10 ) 00246 t += letbase - '0' - 10; 00247 *--s = t + '0'; 00248 u /= b; 00249 } 00250 00251 if( neg ) { 00252 if( width && ( pad & _PRINTFMT_PAD_ZERO ) ) { 00253 __print_char( ctx, '-' ); 00254 ++pc; 00255 --width; 00256 } else { 00257 *--s = '-'; 00258 } 00259 } 00260 00261 return pc + __print_str( ctx, s, width, pad, print_limit, true ); 00262 } 00263 /* 00264 #if __GNUC__ 00265 int fprintf( __FILE *stream, const char *format, ... ) 00266 { 00267 return 0; 00268 } 00269 #endif 00270 */ 00271 00272 /** 00273 * Print the given arguments, with given format onto string out. 00274 */ 00275 static int __print_fmt( _print_ctx_t* ctx, const char *format, va_list args ) 00276 { 00277 int width; 00278 int pad; 00279 int print_limit; 00280 int pc = 0; 00281 char scr[2]; 00282 00283 for( ; *format != 0; ++format ) { 00284 if( *format == '%' ) { 00285 ++format; 00286 width = pad = print_limit = 0; 00287 00288 if( *format == '\0' ) { 00289 break; 00290 } 00291 00292 if( *format == '%' ) { 00293 goto out; 00294 } 00295 00296 if( *format == '-' ) { 00297 ++format; 00298 pad = _PRINTFMT_PAD_RIGHT; 00299 } 00300 00301 while( *format == '0' ) { 00302 ++format; 00303 pad |= _PRINTFMT_PAD_ZERO; 00304 } 00305 00306 for( ; *format >= '0' && *format <= '9'; ++format ) { 00307 width *= 10; 00308 width += *format - '0'; 00309 } 00310 00311 if( *format == '.' ) { 00312 ++format; 00313 for( ; *format >= '0' && *format <= '9'; ++format ) { 00314 print_limit *= 10; 00315 print_limit += *format - '0'; 00316 } 00317 } 00318 00319 if( 0 == print_limit ) { 00320 print_limit--; 00321 } 00322 00323 if( *format == 'l' ) { 00324 ++format; 00325 } 00326 00327 if( *format == 's' ) { 00328 register char *s = (char *) va_arg( args, int ); 00329 pc += __print_str( ctx, 00330 s ? s : "(null)", 00331 width, 00332 pad, 00333 print_limit, 00334 false ); 00335 continue; 00336 } 00337 00338 if( *format == 'd' ) { 00339 pc += __print_int( ctx, va_arg( args, int ), 10, 1, width, pad, 'a', print_limit ); 00340 continue; 00341 } 00342 00343 if( ( *format == 'x' ) || ( *format == 'p' ) ) { 00344 pc += __print_int( ctx, va_arg( args, int ), 16, 0, width, pad, 'a', print_limit ); 00345 continue; 00346 } 00347 00348 if( *format == 'X' ) { 00349 pc += __print_int( ctx, va_arg( args, int ), 16, 0, width, pad, 'A', print_limit ); 00350 continue; 00351 } 00352 00353 if( *format == 'u' ) { 00354 pc += __print_int( ctx, va_arg( args, int ), 10, 0, width, pad, 'a', print_limit ); 00355 continue; 00356 } 00357 00358 if( *format == 'c' ) { 00359 // char are converted to int then pushed on the stack 00360 scr[0] = (char) va_arg( args, int ); 00361 scr[1] = '\0'; 00362 pc += __print_str( ctx, scr, width, pad, print_limit, false ); 00363 continue; 00364 } 00365 } else { 00366 out: 00367 __print_char( ctx, *format ); 00368 ++pc; 00369 } 00370 } 00371 00372 if( ctx && ctx->_max_len ) { 00373 *(ctx->_ptr) = '\0'; 00374 } 00375 00376 return pc; 00377 } 00378 00379 #define BLOCK_MEM_SIZE 1024 00380 00381 int sprintf( char *out, const char *format, ... ) 00382 { 00383 int retval = 0; 00384 _print_ctx_t ctx; 00385 va_list args; 00386 00387 ctx._ptr = out; 00388 ctx._max_len = BLOCK_MEM_SIZE; 00389 00390 va_start( args, format ); 00391 retval = __print_fmt( &ctx, format, args ); 00392 va_end( args ); 00393 00394 return retval; 00395 } 00396 00397 int printf( const char *format, ... ) 00398 { 00399 int retval = 0; 00400 // memory_t* buf; 00401 va_list args; 00402 00403 /* 00404 buf = memory_alloc( 10 ); 00405 00406 if( buf ) { 00407 _print_ctx_t ctx; 00408 ctx._ptr = (char*)buf->_data; 00409 ctx._max_len = BLOCK_MEM_SIZE; 00410 00411 va_start( args, format ); 00412 retval = __print_fmt( &ctx, format, args ); 00413 va_end( args ); 00414 00415 buf->_len = strlen( (const char*)buf->_data ); 00416 00417 // LCD_WriteString( ll, buf ); 00418 ll++; 00419 ll &= 0x03; 00420 if( uart_task_send( buf ) == false ) { 00421 memory_free( buf ); 00422 } 00423 } 00424 */ 00425 00426 va_start( args, format ); 00427 retval = __print_fmt( NULL, format, args ); 00428 va_end( args ); 00429 00430 return retval; 00431 }