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