| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 6 | kaklik | /*! \file rprintf.c \brief printf routine and associated routines. */ |
| 2 | //***************************************************************************** |
||
| 3 | // |
||
| 4 | // File Name : 'rprintf.c' |
||
| 5 | // Title : printf routine and associated routines |
||
| 6 | // Author : Pascal Stang - Copyright (C) 2000-2002 |
||
| 7 | // Created : 2000.12.26 |
||
| 8 | // Revised : 2003.5.1 |
||
| 9 | // Version : 1.0 |
||
| 10 | // Target MCU : Atmel AVR series and other targets |
||
| 11 | // Editor Tabs : 4 |
||
| 12 | // |
||
| 13 | // NOTE: This code is currently below version 1.0, and therefore is considered |
||
| 14 | // to be lacking in some functionality or documentation, or may not be fully |
||
| 15 | // tested. Nonetheless, you can expect most functions to work. |
||
| 16 | // |
||
| 17 | // This code is distributed under the GNU Public License |
||
| 18 | // which can be found at http://www.gnu.org/licenses/gpl.txt |
||
| 19 | // |
||
| 20 | //***************************************************************************** |
||
| 21 | |||
| 22 | #include <avr/pgmspace.h> |
||
| 23 | //#include <string-avr.h> |
||
| 24 | //#include <stdlib.h> |
||
| 25 | #include <stdarg.h> |
||
| 26 | #include "global.h" |
||
| 27 | #include "rprintf.h" |
||
| 28 | |||
| 29 | #ifndef TRUE |
||
| 30 | #define TRUE -1 |
||
| 31 | #define FALSE 0 |
||
| 32 | #endif |
||
| 33 | |||
| 34 | #define INF 32766 // maximum field size to print |
||
| 35 | #define READMEMBYTE(a,char_ptr) ((a)?(pgm_read_byte(char_ptr)):(*char_ptr)) |
||
| 36 | |||
| 37 | #ifdef RPRINTF_COMPLEX |
||
| 38 | static unsigned char buf[128]; |
||
| 39 | #endif |
||
| 40 | |||
| 41 | // use this to store hex conversion in RAM |
||
| 42 | //static char HexChars[] = "0123456789ABCDEF"; |
||
| 43 | // use this to store hex conversion in program memory |
||
| 44 | //static prog_char HexChars[] = "0123456789ABCDEF"; |
||
| 45 | static char __attribute__ ((progmem)) HexChars[] = "0123456789ABCDEF"; |
||
| 46 | |||
| 47 | #define hexchar(x) pgm_read_byte( HexChars+((x)&0x0f) ) |
||
| 48 | //#define hexchar(x) ((((x)&0x0F)>9)?((x)+'A'-10):((x)+'0')) |
||
| 49 | |||
| 50 | // function pointer to single character output routine |
||
| 51 | static void (*rputchar)(unsigned char c); |
||
| 52 | |||
| 53 | // *** rprintf initialization *** |
||
| 54 | // you must call this function once and supply the character output |
||
| 55 | // routine before using other functions in this library |
||
| 56 | void rprintfInit(void (*putchar_func)(unsigned char c)) |
||
| 57 | { |
||
| 58 | rputchar = putchar_func; |
||
| 59 | } |
||
| 60 | |||
| 61 | // *** rprintfChar *** |
||
| 62 | // send a character/byte to the current output device |
||
| 63 | void rprintfChar(unsigned char c) |
||
| 64 | { |
||
| 65 | // do LF -> CR/LF translation |
||
| 66 | if(c == '\n') |
||
| 67 | rputchar('\r'); |
||
| 68 | // send character |
||
| 69 | rputchar(c); |
||
| 70 | } |
||
| 71 | |||
| 72 | // *** rprintfStr *** |
||
| 73 | // prints a null-terminated string stored in RAM |
||
| 74 | void rprintfStr(char str[]) |
||
| 75 | { |
||
| 76 | // send a string stored in RAM |
||
| 77 | // check to make sure we have a good pointer |
||
| 78 | if (!str) return; |
||
| 79 | |||
| 80 | // print the string until a null-terminator |
||
| 81 | while (*str) |
||
| 82 | rprintfChar(*str++); |
||
| 83 | } |
||
| 84 | |||
| 85 | // *** rprintfStrLen *** |
||
| 86 | // prints a section of a string stored in RAM |
||
| 87 | // begins printing at position indicated by <start> |
||
| 88 | // prints number of characters indicated by <len> |
||
| 89 | void rprintfStrLen(char str[], unsigned int start, unsigned int len) |
||
| 90 | { |
||
| 91 | register int i=0; |
||
| 92 | |||
| 93 | // check to make sure we have a good pointer |
||
| 94 | if (!str) return; |
||
| 95 | // spin through characters up to requested start |
||
| 96 | // keep going as long as there's no null |
||
| 97 | while((i++<start) && (*str++)); |
||
| 98 | // for(i=0; i<start; i++) |
||
| 99 | // { |
||
| 100 | // // keep steping through string as long as there's no null |
||
| 101 | // if(*str) str++; |
||
| 102 | // } |
||
| 103 | |||
| 104 | // then print exactly len characters |
||
| 105 | for(i=0; i<len; i++) |
||
| 106 | { |
||
| 107 | // print data out of the string as long as we haven't reached a null yet |
||
| 108 | // at the null, start printing spaces |
||
| 109 | if(*str) |
||
| 110 | rprintfChar(*str++); |
||
| 111 | else |
||
| 112 | rprintfChar(' '); |
||
| 113 | } |
||
| 114 | |||
| 115 | } |
||
| 116 | |||
| 117 | // *** rprintfProgStr *** |
||
| 118 | // prints a null-terminated string stored in program ROM |
||
| 119 | void rprintfProgStr(const prog_char str[]) |
||
| 120 | { |
||
| 121 | // print a string stored in program memory |
||
| 122 | register char c; |
||
| 123 | |||
| 124 | // check to make sure we have a good pointer |
||
| 125 | if (!str) return; |
||
| 126 | |||
| 127 | // print the string until the null-terminator |
||
| 128 | while((c = pgm_read_byte(str++))) |
||
| 129 | rprintfChar(c); |
||
| 130 | } |
||
| 131 | |||
| 132 | // *** rprintfCRLF *** |
||
| 133 | // prints carriage return and line feed |
||
| 134 | void rprintfCRLF(void) |
||
| 135 | { |
||
| 136 | // print CR/LF |
||
| 137 | //rprintfChar('\r'); |
||
| 138 | // LF -> CR/LF translation built-in to rprintfChar() |
||
| 139 | rprintfChar('\n'); |
||
| 140 | } |
||
| 141 | |||
| 142 | // *** rprintfu04 *** |
||
| 143 | // prints an unsigned 4-bit number in hex (1 digit) |
||
| 144 | void rprintfu04(unsigned char data) |
||
| 145 | { |
||
| 146 | // print 4-bit hex value |
||
| 147 | // char Character = data&0x0f; |
||
| 148 | // if (Character>9) |
||
| 149 | // Character+='A'-10; |
||
| 150 | // else |
||
| 151 | // Character+='0'; |
||
| 152 | rprintfChar(hexchar(data)); |
||
| 153 | } |
||
| 154 | |||
| 155 | // *** rprintfu08 *** |
||
| 156 | // prints an unsigned 8-bit number in hex (2 digits) |
||
| 157 | void rprintfu08(unsigned char data) |
||
| 158 | { |
||
| 159 | // print 8-bit hex value |
||
| 160 | rprintfu04(data>>4); |
||
| 161 | rprintfu04(data); |
||
| 162 | } |
||
| 163 | |||
| 164 | // *** rprintfu16 *** |
||
| 165 | // prints an unsigned 16-bit number in hex (4 digits) |
||
| 166 | void rprintfu16(unsigned short data) |
||
| 167 | { |
||
| 168 | // print 16-bit hex value |
||
| 169 | rprintfu08(data>>8); |
||
| 170 | rprintfu08(data); |
||
| 171 | } |
||
| 172 | |||
| 173 | // *** rprintfu32 *** |
||
| 174 | // prints an unsigned 32-bit number in hex (8 digits) |
||
| 175 | void rprintfu32(unsigned long data) |
||
| 176 | { |
||
| 177 | // print 32-bit hex value |
||
| 178 | rprintfu16(data>>16); |
||
| 179 | rprintfu16(data); |
||
| 180 | } |
||
| 181 | |||
| 182 | // *** rprintfNum *** |
||
| 183 | // special printf for numbers only |
||
| 184 | // see formatting information below |
||
| 185 | // Print the number "n" in the given "base" |
||
| 186 | // using exactly "numDigits" |
||
| 187 | // print +/- if signed flag "isSigned" is TRUE |
||
| 188 | // use the character specified in "padchar" to pad extra characters |
||
| 189 | // |
||
| 190 | // Examples: |
||
| 191 | // uartPrintfNum(10, 6, TRUE, ' ', 1234); --> " +1234" |
||
| 192 | // uartPrintfNum(10, 6, FALSE, '0', 1234); --> "001234" |
||
| 193 | // uartPrintfNum(16, 6, FALSE, '.', 0x5AA5); --> "..5AA5" |
||
| 194 | void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n) |
||
| 195 | { |
||
| 196 | // define a global HexChars or use line below |
||
| 197 | //static char HexChars[16] = "0123456789ABCDEF"; |
||
| 198 | char *p, buf[32]; |
||
| 199 | unsigned long x; |
||
| 200 | unsigned char count; |
||
| 201 | |||
| 202 | // prepare negative number |
||
| 203 | if( isSigned && (n < 0) ) |
||
| 204 | { |
||
| 205 | x = -n; |
||
| 206 | } |
||
| 207 | else |
||
| 208 | { |
||
| 209 | x = n; |
||
| 210 | } |
||
| 211 | |||
| 212 | // setup little string buffer |
||
| 213 | count = (numDigits-1)-(isSigned?1:0); |
||
| 214 | p = buf + sizeof (buf); |
||
| 215 | *--p = '\0'; |
||
| 216 | |||
| 217 | // force calculation of first digit |
||
| 218 | // (to prevent zero from not printing at all!!!) |
||
| 219 | *--p = hexchar(x%base); x /= base; |
||
| 220 | // calculate remaining digits |
||
| 221 | while(count--) |
||
| 222 | { |
||
| 223 | if(x != 0) |
||
| 224 | { |
||
| 225 | // calculate next digit |
||
| 226 | *--p = hexchar(x%base); x /= base; |
||
| 227 | } |
||
| 228 | else |
||
| 229 | { |
||
| 230 | // no more digits left, pad out to desired length |
||
| 231 | *--p = padchar; |
||
| 232 | } |
||
| 233 | } |
||
| 234 | |||
| 235 | // apply signed notation if requested |
||
| 236 | if( isSigned ) |
||
| 237 | { |
||
| 238 | if(n < 0) |
||
| 239 | { |
||
| 240 | *--p = '-'; |
||
| 241 | } |
||
| 242 | else if(n > 0) |
||
| 243 | { |
||
| 244 | *--p = '+'; |
||
| 245 | } |
||
| 246 | else |
||
| 247 | { |
||
| 248 | *--p = ' '; |
||
| 249 | } |
||
| 250 | } |
||
| 251 | |||
| 252 | // print the string right-justified |
||
| 253 | count = numDigits; |
||
| 254 | while(count--) |
||
| 255 | { |
||
| 256 | rprintfChar(*p++); |
||
| 257 | } |
||
| 258 | } |
||
| 259 | |||
| 260 | #ifdef RPRINTF_FLOAT |
||
| 261 | // *** rprintfFloat *** |
||
| 262 | // floating-point print |
||
| 263 | void rprintfFloat(char numDigits, double x) |
||
| 264 | { |
||
| 265 | unsigned char firstplace = FALSE; |
||
| 266 | unsigned char negative; |
||
| 267 | unsigned char i, digit; |
||
| 268 | double place = 1.0; |
||
| 269 | |||
| 270 | // save sign |
||
| 271 | negative = (x<0); |
||
| 272 | // convert to absolute value |
||
| 273 | x = (x>0)?(x):(-x); |
||
| 274 | |||
| 275 | // find starting digit place |
||
| 276 | for(i=0; i<15; i++) |
||
| 277 | { |
||
| 278 | if((x/place) < 10.0) |
||
| 279 | break; |
||
| 280 | else |
||
| 281 | place *= 10.0; |
||
| 282 | } |
||
| 283 | // print polarity character |
||
| 284 | if(negative) |
||
| 285 | rprintfChar('-'); |
||
| 286 | else |
||
| 287 | rprintfChar('+'); |
||
| 288 | |||
| 289 | // print digits |
||
| 290 | for(i=0; i<numDigits; i++) |
||
| 291 | { |
||
| 292 | digit = (x/place); |
||
| 293 | |||
| 294 | if(digit | firstplace | (place == 1.0)) |
||
| 295 | { |
||
| 296 | firstplace = TRUE; |
||
| 297 | rprintfChar(digit+0x30); |
||
| 298 | } |
||
| 299 | else |
||
| 300 | rprintfChar(' '); |
||
| 301 | |||
| 302 | if(place == 1.0) |
||
| 303 | { |
||
| 304 | rprintfChar('.'); |
||
| 305 | } |
||
| 306 | |||
| 307 | x -= (digit*place); |
||
| 308 | place /= 10.0; |
||
| 309 | } |
||
| 310 | } |
||
| 311 | #endif |
||
| 312 | |||
| 313 | #ifdef RPRINTF_SIMPLE |
||
| 314 | // *** rprintf1RamRom *** |
||
| 315 | // called by rprintf() - does a simple printf (supports %d, %x, %c) |
||
| 316 | // Supports: |
||
| 317 | // %d - decimal |
||
| 318 | // %x - hex |
||
| 319 | // %c - character |
||
| 320 | int rprintf1RamRom(unsigned char stringInRom, const char *format, ...) |
||
| 321 | { |
||
| 322 | // simple printf routine |
||
| 323 | // define a global HexChars or use line below |
||
| 324 | //static char HexChars[16] = "0123456789ABCDEF"; |
||
| 325 | char format_flag; |
||
| 326 | unsigned int u_val, div_val, base; |
||
| 327 | va_list ap; |
||
| 328 | |||
| 329 | va_start(ap, format); |
||
| 330 | for (;;) |
||
| 331 | { |
||
| 332 | while ((format_flag = READMEMBYTE(stringInRom,format++) ) != '%') |
||
| 333 | { // Until '%' or '\0' |
||
| 334 | if (!format_flag) |
||
| 335 | { |
||
| 336 | va_end(ap); |
||
| 337 | return(0); |
||
| 338 | } |
||
| 339 | rprintfChar(format_flag); |
||
| 340 | } |
||
| 341 | |||
| 342 | switch (format_flag = READMEMBYTE(stringInRom,format++) ) |
||
| 343 | { |
||
| 344 | case 'c': format_flag = va_arg(ap,int); |
||
| 345 | default: rprintfChar(format_flag); continue; |
||
| 346 | case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP; |
||
| 347 | // case 'x': base = 16; div_val = 0x10; |
||
| 348 | case 'x': base = 16; div_val = 0x1000; |
||
| 349 | |||
| 350 | CONVERSION_LOOP: |
||
| 351 | u_val = va_arg(ap,int); |
||
| 352 | if (format_flag == 'd') |
||
| 353 | { |
||
| 354 | if (((int)u_val) < 0) |
||
| 355 | { |
||
| 356 | u_val = - u_val; |
||
| 357 | rprintfChar('-'); |
||
| 358 | } |
||
| 359 | while (div_val > 1 && div_val > u_val) div_val /= 10; |
||
| 360 | } |
||
| 361 | do |
||
| 362 | { |
||
| 363 | //rprintfChar(pgm_read_byte(HexChars+(u_val/div_val))); |
||
| 364 | rprintfu04(u_val/div_val); |
||
| 365 | u_val %= div_val; |
||
| 366 | div_val /= base; |
||
| 367 | } while (div_val); |
||
| 368 | } |
||
| 369 | } |
||
| 370 | va_end(ap); |
||
| 371 | } |
||
| 372 | #endif |
||
| 373 | |||
| 374 | |||
| 375 | #ifdef RPRINTF_COMPLEX |
||
| 376 | // *** rprintf2RamRom *** |
||
| 377 | // called by rprintf() - does a more powerful printf (supports %d, %u, %o, %x, %c, %s) |
||
| 378 | // Supports: |
||
| 379 | // %d - decimal |
||
| 380 | // %u - unsigned decimal |
||
| 381 | // %o - octal |
||
| 382 | // %x - hex |
||
| 383 | // %c - character |
||
| 384 | // %s - strings |
||
| 385 | // and the width,precision,padding modifiers |
||
| 386 | // **this printf does not support floating point numbers |
||
| 387 | int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...) |
||
| 388 | { |
||
| 389 | register unsigned char *f, *bp; |
||
| 390 | register long l; |
||
| 391 | register unsigned long u; |
||
| 392 | register int i; |
||
| 393 | register int fmt; |
||
| 394 | register unsigned char pad = ' '; |
||
| 395 | int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0; |
||
| 396 | int sign = 0; |
||
| 397 | |||
| 398 | va_list ap; |
||
| 399 | va_start(ap, sfmt); |
||
| 400 | |||
| 401 | f = (unsigned char *) sfmt; |
||
| 402 | |||
| 403 | for (; READMEMBYTE(stringInRom,f); f++) |
||
| 404 | { |
||
| 405 | if (READMEMBYTE(stringInRom,f) != '%') |
||
| 406 | { // not a format character |
||
| 407 | // then just output the char |
||
| 408 | rprintfChar(READMEMBYTE(stringInRom,f)); |
||
| 409 | } |
||
| 410 | else |
||
| 411 | { |
||
| 412 | f++; // if we have a "%" then skip it |
||
| 413 | if (READMEMBYTE(stringInRom,f) == '-') |
||
| 414 | { |
||
| 415 | flush_left = 1; // minus: flush left |
||
| 416 | f++; |
||
| 417 | } |
||
| 418 | if (READMEMBYTE(stringInRom,f) == '0' |
||
| 419 | || READMEMBYTE(stringInRom,f) == '.') |
||
| 420 | { |
||
| 421 | // padding with 0 rather than blank |
||
| 422 | pad = '0'; |
||
| 423 | f++; |
||
| 424 | } |
||
| 425 | if (READMEMBYTE(stringInRom,f) == '*') |
||
| 426 | { // field width |
||
| 427 | f_width = va_arg(ap, int); |
||
| 428 | f++; |
||
| 429 | } |
||
| 430 | else if (Isdigit(READMEMBYTE(stringInRom,f))) |
||
| 431 | { |
||
| 432 | f_width = atoiRamRom(stringInRom, (char *) f); |
||
| 433 | while (Isdigit(READMEMBYTE(stringInRom,f))) |
||
| 434 | f++; // skip the digits |
||
| 435 | } |
||
| 436 | if (READMEMBYTE(stringInRom,f) == '.') |
||
| 437 | { // precision |
||
| 438 | f++; |
||
| 439 | if (READMEMBYTE(stringInRom,f) == '*') |
||
| 440 | { |
||
| 441 | prec = va_arg(ap, int); |
||
| 442 | f++; |
||
| 443 | } |
||
| 444 | else if (Isdigit(READMEMBYTE(stringInRom,f))) |
||
| 445 | { |
||
| 446 | prec = atoiRamRom(stringInRom, (char *) f); |
||
| 447 | while (Isdigit(READMEMBYTE(stringInRom,f))) |
||
| 448 | f++; // skip the digits |
||
| 449 | } |
||
| 450 | } |
||
| 451 | if (READMEMBYTE(stringInRom,f) == '#') |
||
| 452 | { // alternate form |
||
| 453 | hash = 1; |
||
| 454 | f++; |
||
| 455 | } |
||
| 456 | if (READMEMBYTE(stringInRom,f) == 'l') |
||
| 457 | { // long format |
||
| 458 | do_long = 1; |
||
| 459 | f++; |
||
| 460 | } |
||
| 461 | |||
| 462 | fmt = READMEMBYTE(stringInRom,f); |
||
| 463 | bp = buf; |
||
| 464 | switch (fmt) { // do the formatting |
||
| 465 | case 'd': // 'd' signed decimal |
||
| 466 | if (do_long) |
||
| 467 | l = va_arg(ap, long); |
||
| 468 | else |
||
| 469 | l = (long) (va_arg(ap, int)); |
||
| 470 | if (l < 0) |
||
| 471 | { |
||
| 472 | sign = 1; |
||
| 473 | l = -l; |
||
| 474 | } |
||
| 475 | do { |
||
| 476 | *bp++ = l % 10 + '0'; |
||
| 477 | } while ((l /= 10) > 0); |
||
| 478 | if (sign) |
||
| 479 | *bp++ = '-'; |
||
| 480 | f_width = f_width - (bp - buf); |
||
| 481 | if (!flush_left) |
||
| 482 | while (f_width-- > 0) |
||
| 483 | rprintfChar(pad); |
||
| 484 | for (bp--; bp >= buf; bp--) |
||
| 485 | rprintfChar(*bp); |
||
| 486 | if (flush_left) |
||
| 487 | while (f_width-- > 0) |
||
| 488 | rprintfChar(' '); |
||
| 489 | break; |
||
| 490 | case 'o': // 'o' octal number |
||
| 491 | case 'x': // 'x' hex number |
||
| 492 | case 'u': // 'u' unsigned decimal |
||
| 493 | if (do_long) |
||
| 494 | u = va_arg(ap, unsigned long); |
||
| 495 | else |
||
| 496 | u = (unsigned long) (va_arg(ap, unsigned)); |
||
| 497 | if (fmt == 'u') |
||
| 498 | { // unsigned decimal |
||
| 499 | do { |
||
| 500 | *bp++ = u % 10 + '0'; |
||
| 501 | } while ((u /= 10) > 0); |
||
| 502 | } |
||
| 503 | else if (fmt == 'o') |
||
| 504 | { // octal |
||
| 505 | do { |
||
| 506 | *bp++ = u % 8 + '0'; |
||
| 507 | } while ((u /= 8) > 0); |
||
| 508 | if (hash) |
||
| 509 | *bp++ = '0'; |
||
| 510 | } |
||
| 511 | else if (fmt == 'x') |
||
| 512 | { // hex |
||
| 513 | do { |
||
| 514 | i = u % 16; |
||
| 515 | if (i < 10) |
||
| 516 | *bp++ = i + '0'; |
||
| 517 | else |
||
| 518 | *bp++ = i - 10 + 'a'; |
||
| 519 | } while ((u /= 16) > 0); |
||
| 520 | if (hash) |
||
| 521 | { |
||
| 522 | *bp++ = 'x'; |
||
| 523 | *bp++ = '0'; |
||
| 524 | } |
||
| 525 | } |
||
| 526 | i = f_width - (bp - buf); |
||
| 527 | if (!flush_left) |
||
| 528 | while (i-- > 0) |
||
| 529 | rprintfChar(pad); |
||
| 530 | for (bp--; bp >= buf; bp--) |
||
| 531 | rprintfChar((int) (*bp)); |
||
| 532 | if (flush_left) |
||
| 533 | while (i-- > 0) |
||
| 534 | rprintfChar(' '); |
||
| 535 | break; |
||
| 536 | case 'c': // 'c' character |
||
| 537 | i = va_arg(ap, int); |
||
| 538 | rprintfChar((int) (i)); |
||
| 539 | break; |
||
| 540 | case 's': // 's' string |
||
| 541 | bp = va_arg(ap, unsigned char *); |
||
| 542 | if (!bp) |
||
| 543 | bp = (unsigned char *) "(nil)"; |
||
| 544 | f_width = f_width - strlen((char *) bp); |
||
| 545 | if (!flush_left) |
||
| 546 | while (f_width-- > 0) |
||
| 547 | rprintfChar(pad); |
||
| 548 | for (i = 0; *bp && i < prec; i++) |
||
| 549 | { |
||
| 550 | rprintfChar(*bp); |
||
| 551 | bp++; |
||
| 552 | } |
||
| 553 | if (flush_left) |
||
| 554 | while (f_width-- > 0) |
||
| 555 | rprintfChar(' '); |
||
| 556 | break; |
||
| 557 | case '%': // '%' character |
||
| 558 | rprintfChar('%'); |
||
| 559 | break; |
||
| 560 | } |
||
| 561 | flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0; |
||
| 562 | sign = 0; |
||
| 563 | pad = ' '; |
||
| 564 | } |
||
| 565 | } |
||
| 566 | |||
| 567 | va_end(ap); |
||
| 568 | return 0; |
||
| 569 | } |
||
| 570 | |||
| 571 | unsigned char Isdigit(char c) |
||
| 572 | { |
||
| 573 | if((c >= 0x30) && (c <= 0x39)) |
||
| 574 | return TRUE; |
||
| 575 | else |
||
| 576 | return FALSE; |
||
| 577 | } |
||
| 578 | |||
| 579 | int atoiRamRom(unsigned char stringInRom, char *str) |
||
| 580 | { |
||
| 581 | int num = 0;; |
||
| 582 | |||
| 583 | while(Isdigit(READMEMBYTE(stringInRom,str))) |
||
| 584 | { |
||
| 585 | num *= 10; |
||
| 586 | num += ((READMEMBYTE(stringInRom,str++)) - 0x30); |
||
| 587 | } |
||
| 588 | return num; |
||
| 589 | } |
||
| 590 | |||
| 591 | #endif |
||
| 592 | |||
| 593 | //****************************************************************************** |
||
| 594 | // code below this line is commented out and can be ignored |
||
| 595 | //****************************************************************************** |
||
| 596 | /* |
||
| 597 | char* sprintf(const char *sfmt, ...) |
||
| 598 | { |
||
| 599 | register unsigned char *f, *bp, *str; |
||
| 600 | register long l; |
||
| 601 | register unsigned long u; |
||
| 602 | register int i; |
||
| 603 | register int fmt; |
||
| 604 | register unsigned char pad = ' '; |
||
| 605 | int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0; |
||
| 606 | int sign = 0; |
||
| 607 | |||
| 608 | va_list ap; |
||
| 609 | va_start(ap, sfmt); |
||
| 610 | |||
| 611 | str = bufstring; |
||
| 612 | f = (unsigned char *) sfmt; |
||
| 613 | |||
| 614 | for (; *f; f++) |
||
| 615 | { |
||
| 616 | if (*f != '%') |
||
| 617 | { // not a format character |
||
| 618 | *str++ = (*f); // then just output the char |
||
| 619 | } |
||
| 620 | else |
||
| 621 | { |
||
| 622 | f++; // if we have a "%" then skip it |
||
| 623 | if (*f == '-') |
||
| 624 | { |
||
| 625 | flush_left = 1; // minus: flush left |
||
| 626 | f++; |
||
| 627 | } |
||
| 628 | if (*f == '0' || *f == '.') |
||
| 629 | { |
||
| 630 | // padding with 0 rather than blank |
||
| 631 | pad = '0'; |
||
| 632 | f++; |
||
| 633 | } |
||
| 634 | if (*f == '*') |
||
| 635 | { // field width |
||
| 636 | f_width = va_arg(ap, int); |
||
| 637 | f++; |
||
| 638 | } |
||
| 639 | else if (Isdigit(*f)) |
||
| 640 | { |
||
| 641 | f_width = atoi((char *) f); |
||
| 642 | while (Isdigit(*f)) |
||
| 643 | f++; // skip the digits |
||
| 644 | } |
||
| 645 | if (*f == '.') |
||
| 646 | { // precision |
||
| 647 | f++; |
||
| 648 | if (*f == '*') |
||
| 649 | { |
||
| 650 | prec = va_arg(ap, int); |
||
| 651 | f++; |
||
| 652 | } |
||
| 653 | else if (Isdigit(*f)) |
||
| 654 | { |
||
| 655 | prec = atoi((char *) f); |
||
| 656 | while (Isdigit(*f)) |
||
| 657 | f++; // skip the digits |
||
| 658 | } |
||
| 659 | } |
||
| 660 | if (*f == '#') |
||
| 661 | { // alternate form |
||
| 662 | hash = 1; |
||
| 663 | f++; |
||
| 664 | } |
||
| 665 | if (*f == 'l') |
||
| 666 | { // long format |
||
| 667 | do_long = 1; |
||
| 668 | f++; |
||
| 669 | } |
||
| 670 | |||
| 671 | fmt = *f; |
||
| 672 | bp = buf; |
||
| 673 | switch (fmt) { // do the formatting |
||
| 674 | case 'd': // 'd' signed decimal |
||
| 675 | if (do_long) |
||
| 676 | l = va_arg(ap, long); |
||
| 677 | else |
||
| 678 | l = (long) (va_arg(ap, int)); |
||
| 679 | if (l < 0) |
||
| 680 | { |
||
| 681 | sign = 1; |
||
| 682 | l = -l; |
||
| 683 | } |
||
| 684 | do { |
||
| 685 | *bp++ = l % 10 + '0'; |
||
| 686 | } while ((l /= 10) > 0); |
||
| 687 | if (sign) |
||
| 688 | *bp++ = '-'; |
||
| 689 | f_width = f_width - (bp - buf); |
||
| 690 | if (!flush_left) |
||
| 691 | while (f_width-- > 0) |
||
| 692 | *str++ = (pad); |
||
| 693 | for (bp--; bp >= buf; bp--) |
||
| 694 | *str++ = (*bp); |
||
| 695 | if (flush_left) |
||
| 696 | while (f_width-- > 0) |
||
| 697 | *str++ = (' '); |
||
| 698 | break; |
||
| 699 | case 'o': // 'o' octal number |
||
| 700 | case 'x': // 'x' hex number |
||
| 701 | case 'u': // 'u' unsigned decimal |
||
| 702 | if (do_long) |
||
| 703 | u = va_arg(ap, unsigned long); |
||
| 704 | else |
||
| 705 | u = (unsigned long) (va_arg(ap, unsigned)); |
||
| 706 | if (fmt == 'u') |
||
| 707 | { // unsigned decimal |
||
| 708 | do { |
||
| 709 | *bp++ = u % 10 + '0'; |
||
| 710 | } while ((u /= 10) > 0); |
||
| 711 | } |
||
| 712 | else if (fmt == 'o') |
||
| 713 | { // octal |
||
| 714 | do { |
||
| 715 | *bp++ = u % 8 + '0'; |
||
| 716 | } while ((u /= 8) > 0); |
||
| 717 | if (hash) |
||
| 718 | *bp++ = '0'; |
||
| 719 | } |
||
| 720 | else if (fmt == 'x') |
||
| 721 | { // hex |
||
| 722 | do { |
||
| 723 | i = u % 16; |
||
| 724 | if (i < 10) |
||
| 725 | *bp++ = i + '0'; |
||
| 726 | else |
||
| 727 | *bp++ = i - 10 + 'a'; |
||
| 728 | } while ((u /= 16) > 0); |
||
| 729 | if (hash) |
||
| 730 | { |
||
| 731 | *bp++ = 'x'; |
||
| 732 | *bp++ = '0'; |
||
| 733 | } |
||
| 734 | } |
||
| 735 | i = f_width - (bp - buf); |
||
| 736 | if (!flush_left) |
||
| 737 | while (i-- > 0) |
||
| 738 | *str++ = (pad); |
||
| 739 | for (bp--; bp >= buf; bp--) |
||
| 740 | *str++ = ((int) (*bp)); |
||
| 741 | if (flush_left) |
||
| 742 | while (i-- > 0) |
||
| 743 | *str++ = (' '); |
||
| 744 | break; |
||
| 745 | case 'c': // 'c' character |
||
| 746 | i = va_arg(ap, int); |
||
| 747 | *str++ = ((int) (i)); |
||
| 748 | break; |
||
| 749 | case 's': // 's' string |
||
| 750 | bp = va_arg(ap, unsigned char *); |
||
| 751 | if (!bp) |
||
| 752 | bp = (unsigned char *) "(nil)"; |
||
| 753 | f_width = f_width - strlen((char *) bp); |
||
| 754 | if (!flush_left) |
||
| 755 | while (f_width-- > 0) |
||
| 756 | *str++ = (pad); |
||
| 757 | for (i = 0; *bp && i < prec; i++) |
||
| 758 | { |
||
| 759 | *str++ = (*bp); |
||
| 760 | bp++; |
||
| 761 | } |
||
| 762 | if (flush_left) |
||
| 763 | while (f_width-- > 0) |
||
| 764 | *str++ = (' '); |
||
| 765 | break; |
||
| 766 | case '%': // '%' character |
||
| 767 | *str++ = ('%'); |
||
| 768 | break; |
||
| 769 | } |
||
| 770 | flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0; |
||
| 771 | sign = 0; |
||
| 772 | pad = ' '; |
||
| 773 | } |
||
| 774 | } |
||
| 775 | |||
| 776 | va_end(ap); |
||
| 777 | // terminate string with null |
||
| 778 | *str++ = '\0'; |
||
| 779 | return bufstring; |
||
| 780 | } |
||
| 781 | |||
| 782 | */ |
Powered by WebSVN v2.8.3