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 |
*/ |