Subversion Repositories NaviCtrl

Rev

Rev 41 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 41 Rev 203
1
/*
1
/*
2
Copyright (C) 1993 Free Software Foundation
2
Copyright (C) 1993 Free Software Foundation
3
 
3
 
4
This file is part of the GNU IO Library.  This library is free
4
This file is part of the GNU IO Library.  This library is free
5
software; you can redistribute it and/or modify it under the
5
software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the
6
terms of the GNU General Public License as published by the
7
Free Software Foundation; either version 2, or (at your option)
7
Free Software Foundation; either version 2, or (at your option)
8
any later version.
8
any later version.
9
 
9
 
10
This library is distributed in the hope that it will be useful,
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
13
GNU General Public License for more details.
14
 
14
 
15
You should have received a copy of the GNU General Public License
15
You should have received a copy of the GNU General Public License
16
along with this library; see the file COPYING.  If not, write to the Free
16
along with this library; see the file COPYING.  If not, write to the Free
17
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
18
 
19
As a special exception, if you link this library with files
19
As a special exception, if you link this library with files
20
compiled with a GNU compiler to produce an executable, this does not cause
20
compiled with a GNU compiler to produce an executable, this does not cause
21
the resulting executable to be covered by the GNU General Public License.
21
the resulting executable to be covered by the GNU General Public License.
22
This exception does not however invalidate any other reasons why
22
This exception does not however invalidate any other reasons why
23
the executable file might be covered by the GNU General Public License. */
23
the executable file might be covered by the GNU General Public License. */
24
 
24
 
25
/*
25
/*
26
 * Copyright (c) 1990 Regents of the University of California.
26
 * Copyright (c) 1990 Regents of the University of California.
27
 * All rights reserved.
27
 * All rights reserved.
28
 *
28
 *
29
 * Redistribution and use in source and binary forms, with or without
29
 * Redistribution and use in source and binary forms, with or without
30
 * modification, are permitted provided that the following conditions
30
 * modification, are permitted provided that the following conditions
31
 * are met:
31
 * are met:
32
 * 1. Redistributions of source code must retain the above copyright
32
 * 1. Redistributions of source code must retain the above copyright
33
 *    notice, this list of conditions and the following disclaimer.
33
 *    notice, this list of conditions and the following disclaimer.
34
 * 2. Redistributions in binary form must reproduce the above copyright
34
 * 2. Redistributions in binary form must reproduce the above copyright
35
 *    notice, this list of conditions and the following disclaimer in the
35
 *    notice, this list of conditions and the following disclaimer in the
36
 *    documentation and/or other materials provided with the distribution.
36
 *    documentation and/or other materials provided with the distribution.
37
 * 3. [rescinded 22 July 1999]
37
 * 3. [rescinded 22 July 1999]
38
 * 4. Neither the name of the University nor the names of its contributors
38
 * 4. Neither the name of the University nor the names of its contributors
39
 *    may be used to endorse or promote products derived from this software
39
 *    may be used to endorse or promote products derived from this software
40
 *    without specific prior written permission.
40
 *    without specific prior written permission.
41
 *
41
 *
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52
 * SUCH DAMAGE.
52
 * SUCH DAMAGE.
53
 */
53
 */
54
 
54
 
55
/* * ****************************************************************************
55
/* * ****************************************************************************
56
 This file is a patched version of printf called _printf_P
56
 This file is a patched version of printf called _printf_P
57
 It is made to work with avr-gcc for Atmel AVR MCUs.
57
 It is made to work with avr-gcc for Atmel AVR MCUs.
58
 There are some differences from standard printf:
58
 There are some differences from standard printf:
59
        1. There is no floating point support (with fp the code is about 8K!)
59
        1. There is no floating point support (with fp the code is about 8K!)
60
        2. Return type is void
60
        2. Return type is void
61
        3. Format string must be in program memory (by using macro printf this is
61
        3. Format string must be in program memory (by using macro printf this is
62
           done automaticaly)
62
           done automaticaly)
63
        4. %n is not implemented (just remove the comment around it if you need it)
63
        4. %n is not implemented (just remove the comment around it if you need it)
64
        5. If LIGHTPRINTF is defined, the code is about 550 bytes smaller and the
64
        5. If LIGHTPRINTF is defined, the code is about 550 bytes smaller and the
65
           folowing specifiers are disabled :
65
           folowing specifiers are disabled :
66
                space # * . - + p s o O
66
                space # * . - + p s o O
67
        6. A function void uart_sendchar(char c) is used for output. The UART must
67
        6. A function void uart_sendchar(char c) is used for output. The UART must
68
                be initialized before using printf.
68
                be initialized before using printf.
69
 
69
 
70
 Alexander Popov
70
 Alexander Popov
71
 sasho@vip.orbitel.bg
71
 sasho@vip.orbitel.bg
72
******************************************************************************
72
******************************************************************************
73
 Changed file to work with LPC - ARM.
73
 Changed file to work with LPC - ARM.
74
 Ingo Busker
74
 Ingo Busker
75
 busker@mikrocontroller.com   02.2005
75
 busker@mikrocontroller.com   02.2005
76
******************************************************************************/
76
******************************************************************************/
77
 
77
 
78
 
78
 
79
/*
79
/*
80
 * Actual printf innards.
80
 * Actual printf innards.
81
 *
81
 *
82
 * This code is large and complicated...
82
 * This code is large and complicated...
83
 */
83
 */
84
 
84
 
85
#include <string.h>
85
#include <string.h>
86
#ifdef __STDC__
86
#ifdef __STDC__
87
#include <stdarg.h>
87
#include <stdarg.h>
88
#else
88
#else
89
#include <varargs.h>
89
#include <varargs.h>
90
#endif
90
#endif
91
#include "91x_lib.h"
91
#include "91x_lib.h"
92
#include "menu.h"
92
#include "printf_P.h"
93
 
-
 
94
 
-
 
95
//#define LIGHTPRINTF
93
 
96
char Putchar(char zeichen)
94
void PRINT(pVoidFnctChar pPutchar, const char * ptr, unsigned int len)
97
{
95
{
98
   DisplayBuff[DispPtr++] = zeichen;
96
        for(;len;len--)
99
   return(1);
97
                (*pPutchar)(*ptr++);
100
}
-
 
101
 
98
}
102
 
-
 
103
void PRINT(const char * ptr, unsigned int len) {
-
 
104
        for(;len;len--)
99
 
105
                Putchar(*ptr++);
-
 
106
}
-
 
107
 
100
void PRINTP(pVoidFnctChar pPutchar, const char * ptr, unsigned int len)
108
void PRINTP(const char * ptr, unsigned int len) {
101
{
109
        for(;len;len--)
102
        for(;len;len--)
110
                Putchar(*ptr++);
103
                (*pPutchar)(*ptr++);
111
}
104
}
112
 
105
 
113
void PAD_SP(signed char howmany) {
106
void PAD_SP(pVoidFnctChar pPutchar, signed char howmany) {
114
        for(;howmany>0;howmany--)
107
        for(;howmany>0;howmany--)
115
                Putchar(' ');
108
                (*pPutchar)(' ');
116
}
109
}
117
 
110
 
118
void PAD_0(signed char howmany) {
111
void PAD_0(pVoidFnctChar pPutchar, signed char howmany) {
119
        for(;howmany>0;howmany--)
112
        for(;howmany>0;howmany--)
120
                Putchar('0');
113
                (*pPutchar)('0');
121
}
114
}
122
 
115
 
123
#define BUF             40
116
#define BUF             40
124
 
117
 
125
/*
118
/*
126
 * Macros for converting digits to letters and vice versa
119
 * Macros for converting digits to letters and vice versa
127
 */
120
 */
128
#define to_digit(c)     ((c) - '0')
121
#define to_digit(c)     ((c) - '0')
129
#define  is_digit(c)    ((c)<='9' && (c)>='0')
122
#define is_digit(c)     ((c)<='9' && (c)>='0')
130
#define to_char(n)      ((n) + '0')
123
#define to_char(n)      ((n) + '0')
131
 
124
 
132
/*
125
/*
133
 * Flags used during conversion.
126
 * Flags used during conversion.
134
 */
127
 */
135
#define LONGINT         0x01            /* long integer */
128
#define LONGINT         0x01            /* long integer */
136
#define LONGDBL         0x02            /* long double; unimplemented */
129
#define LONGDBL         0x02            /* long double; unimplemented */
137
#define SHORTINT                0x04            /* short integer */
130
#define SHORTINT        0x04            /* short integer */
138
#define ALT                     0x08            /* alternate form */
131
#define ALT                     0x08            /* alternate form */
139
#define LADJUST         0x10            /* left adjustment */
132
#define LADJUST         0x10            /* left adjustment */
140
#define ZEROPAD         0x20            /* zero (as opposed to blank) pad */
133
#define ZEROPAD         0x20            /* zero (as opposed to blank) pad */
141
#define HEXPREFIX       0x40            /* add 0x or 0X prefix */
134
#define HEXPREFIX       0x40            /* add 0x or 0X prefix */
142
 
135
 
143
void _printf_P (char const *fmt0, ...)      /* Works with string from FLASH */
136
void _printf_P (pVoidFnctChar pPutchar, char const *fmt0, ...)
144
{
137
{
145
        va_list ap;
138
        va_list ap;
146
        register const char *fmt; /* format string */
139
        register const char *fmt; /* format string */
147
        register char ch;       /* character from fmt */
140
        register char ch;       /* character from fmt */
148
        register int n;         /* handy integer (short term usage) */
141
        register int n;         /* handy integer (short term usage) */
149
        register char *cp;      /* handy char pointer (short term usage) */
142
        register char *cp;      /* handy char pointer (short term usage) */
150
        const char *fmark;      /* for remembering a place in fmt */
143
        const char *fmark;      /* for remembering a place in fmt */
151
        register unsigned char flags;   /* flags as above */
144
        register unsigned char flags;   /* flags as above */
152
        signed char width;              /* width from format (%8d), or 0 */
145
        signed char width;              /* width from format (%8d), or 0 */
153
        signed char prec;               /* precision from format (%.3d), or -1 */
146
        signed char prec;               /* precision from format (%.3d), or -1 */
154
        char sign;                              /* sign prefix (' ', '+', '-', or \0) */
147
        char sign;                              /* sign prefix (' ', '+', '-', or \0) */
155
        unsigned long _ulong=0; /* integer arguments %[diouxX] */
148
        unsigned long _ulong=0; /* integer arguments %[diouxX] */
156
#define OCT 8
149
#define OCT 8
157
#define DEC 10
150
#define DEC 10
158
#define HEX 16
151
#define HEX 16
159
        unsigned char base;             /* base for [diouxX] conversion */
152
        unsigned char base;             /* base for [diouxX] conversion */
160
        signed char dprec;              /* a copy of prec if [diouxX], 0 otherwise */
153
        signed char dprec;              /* a copy of prec if [diouxX], 0 otherwise */
161
        signed char dpad;                       /* extra 0 padding needed for integers */
154
        signed char dpad;                       /* extra 0 padding needed for integers */
162
        signed char fieldsz;            /* field size expanded by sign, dpad etc */
155
        signed char fieldsz;            /* field size expanded by sign, dpad etc */
163
        /* The initialization of 'size' is to suppress a warning that
156
        /* The initialization of 'size' is to suppress a warning that
164
           'size' might be used unitialized.  It seems gcc can't
157
           'size' might be used unitialized.  It seems gcc can't
165
           quite grok this spaghetti code ... */
158
           quite grok this spaghetti code ... */
166
        signed char size = 0;           /* size of converted field or string */
159
        signed char size = 0;           /* size of converted field or string */
167
        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
160
        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
168
        char ox[2];                     /* space for 0x hex-prefix */
161
        char ox[2];                     /* space for 0x hex-prefix */
-
 
162
 
-
 
163
        if(pPutchar == NULL) return;
169
 
164
 
170
        va_start(ap, fmt0);
165
        va_start(ap, fmt0);
171
       
166
 
172
        fmt = fmt0;
167
        fmt = fmt0;
173
 
168
 
174
        /*
169
        /*
175
         * Scan the format for conversions (`%' character).
170
         * Scan the format for conversions (`%' character).
176
         */
171
         */
177
        for (;;) {
172
        for (;;) {
178
                for (fmark = fmt; (ch = (*fmt)) != '\0' && ch != '%'; fmt++)
173
                for (fmark = fmt; (ch = (*fmt)) != '\0' && ch != '%'; fmt++)
179
                        /* void */;
174
                        /* void */;
180
                if ((n = fmt - fmark) != 0) {
175
                if ((n = fmt - fmark) != 0) {
181
                        PRINTP(fmark, n);
176
                        PRINTP(pPutchar, fmark, n);
182
                }
177
                }
183
                if (ch == '\0')
178
                if (ch == '\0')
184
                        goto done;
179
                        goto done;
185
                fmt++;          /* skip over '%' */
180
                fmt++;          /* skip over '%' */
186
 
181
 
187
                flags = 0;
182
                flags = 0;
188
                dprec = 0;
183
                dprec = 0;
189
                width = 0;
184
                width = 0;
190
                prec = -1;
185
                prec = -1;
191
                sign = '\0';
186
                sign = '\0';
192
 
187
 
193
rflag:          ch = (*fmt++);
188
rflag:          ch = (*fmt++);
194
reswitch:
189
reswitch:
195
#ifdef LIGHTPRINTF
190
#ifdef LIGHTPRINTF
196
        if (ch=='o' || ch=='u' || (ch|0x20)=='x') {
191
        if (ch=='o' || ch=='u' || (ch|0x20)=='x') {
197
#else
192
#else
198
        if (ch=='u' || (ch|0x20)=='x') {
193
        if (ch=='u' || (ch|0x20)=='x') {
199
#endif
194
#endif
200
                if (flags&LONGINT) {
195
                if (flags&LONGINT) {
201
                        _ulong=va_arg(ap, unsigned long);
196
                        _ulong=va_arg(ap, unsigned long);
202
                } else {
197
                } else {
203
                        register unsigned int _d;
198
                        register unsigned int _d;
204
                        _d=va_arg(ap, unsigned int);
199
                        _d=va_arg(ap, unsigned int);
205
                        _ulong = flags&SHORTINT ? (unsigned long)(unsigned short)_d : (unsigned long)_d;
200
                        _ulong = flags&SHORTINT ? (unsigned long)(unsigned short)_d : (unsigned long)_d;
206
                }
201
                }
207
        }
202
        }
208
       
203
 
209
#ifndef LIGHTPRINTF
204
#ifndef LIGHTPRINTF
210
                if(ch==' ') {
205
                if(ch==' ') {
211
                        /*
206
                        /*
212
                         * ``If the space and + flags both appear, the space
207
                         * ``If the space and + flags both appear, the space
213
                         * flag will be ignored.''
208
                         * flag will be ignored.''
214
                         *      -- ANSI X3J11
209
                         *      -- ANSI X3J11
215
                         */
210
                         */
216
                        if (!sign)
211
                        if (!sign)
217
                                sign = ' ';
212
                                sign = ' ';
218
                        goto rflag;
213
                        goto rflag;
219
                } else if (ch=='#') {
214
                } else if (ch=='#') {
220
                        flags |= ALT;
215
                        flags |= ALT;
221
                        goto rflag;
216
                        goto rflag;
222
                } else if (ch=='*'||ch=='-') {
217
                } else if (ch=='*'||ch=='-') {
223
                        if (ch=='*') {
218
                        if (ch=='*') {
224
                                /*
219
                                /*
225
                                 * ``A negative field width argument is taken as a
220
                                 * ``A negative field width argument is taken as a
226
                                 * - flag followed by a positive field width.''
221
                                 * - flag followed by a positive field width.''
227
                                 *      -- ANSI X3J11
222
                                 *      -- ANSI X3J11
228
                                 * They don't exclude field widths read from args.
223
                                 * They don't exclude field widths read from args.
229
                                 */
224
                                 */
230
                                if ((width = va_arg(ap, int)) >= 0)
225
                                if ((width = va_arg(ap, int)) >= 0)
231
                                        goto rflag;
226
                                        goto rflag;
232
                                width = -width;
227
                                width = -width;
233
                        }
228
                        }
234
                        flags |= LADJUST;
229
                        flags |= LADJUST;
235
                        flags &= ~ZEROPAD; /* '-' disables '0' */
230
                        flags &= ~ZEROPAD; /* '-' disables '0' */
236
                        goto rflag;
231
                        goto rflag;
237
                } else if (ch=='+') {
232
                } else if (ch=='+') {
238
                        sign = '+';
233
                        sign = '+';
239
                        goto rflag;
234
                        goto rflag;
240
                } else if (ch=='.') {
235
                } else if (ch=='.') {
241
                        if ((ch = (*fmt++)) == '*') {
236
                        if ((ch = (*fmt++)) == '*') {
242
                                n = va_arg(ap, int);
237
                                n = va_arg(ap, int);
243
                                prec = n < 0 ? -1 : n;
238
                                prec = n < 0 ? -1 : n;
244
                                goto rflag;
239
                                goto rflag;
245
                        }
240
                        }
246
                        n = 0;
241
                        n = 0;
247
                        while (is_digit(ch)) {
242
                        while (is_digit(ch)) {
248
                                n = n*10 + to_digit(ch);
243
                                n = n*10 + to_digit(ch);
249
                                ch = (*fmt++);
244
                                ch = (*fmt++);
250
                        }
245
                        }
251
                        prec = n < 0 ? -1 : n;
246
                        prec = n < 0 ? -1 : n;
252
                        goto reswitch;
247
                        goto reswitch;
253
                } else
248
                } else
254
#endif /* LIGHTPRINTF */
249
#endif /* LIGHTPRINTF */
255
                if (ch=='0') {
250
                if (ch=='0') {
256
                        /*
251
                        /*
257
                         * ``Note that 0 is taken as a flag, not as the
252
                         * ``Note that 0 is taken as a flag, not as the
258
                         * beginning of a field width.''
253
                         * beginning of a field width.''
259
                         *      -- ANSI X3J11
254
                         *      -- ANSI X3J11
260
                         */
255
                         */
261
                        if (!(flags & LADJUST))
256
                        if (!(flags & LADJUST))
262
                            flags |= ZEROPAD; /* '-' disables '0' */
257
                            flags |= ZEROPAD; /* '-' disables '0' */
263
                        goto rflag;
258
                        goto rflag;
264
                } else if (ch>='1' && ch<='9') {
259
                } else if (ch>='1' && ch<='9') {
265
                        n = 0;
260
                        n = 0;
266
                        do {
261
                        do {
267
                                n = 10 * n + to_digit(ch);
262
                                n = 10 * n + to_digit(ch);
268
                                ch = *fmt++;
263
                                ch = *fmt++;
269
                        } while (is_digit(ch));
264
                        } while (is_digit(ch));
270
                        width = n;
265
                        width = n;
271
                        goto reswitch;
266
                        goto reswitch;
272
                } else if (ch=='h') {
267
                } else if (ch=='h') {
273
                        flags |= SHORTINT;
268
                        flags |= SHORTINT;
274
                        goto rflag;
269
                        goto rflag;
275
                } else if (ch=='l') {
270
                } else if (ch=='l') {
276
                        flags |= LONGINT;
271
                        flags |= LONGINT;
277
                        goto rflag;
272
                        goto rflag;
278
                } else if (ch=='c') {
273
                } else if (ch=='c') {
279
                        *(cp = buf) = va_arg(ap, int);
274
                        *(cp = buf) = va_arg(ap, int);
280
                        size = 1;
275
                        size = 1;
281
                        sign = '\0';
276
                        sign = '\0';
282
                } else if (ch=='D'||ch=='d'||ch=='i') {
277
                } else if (ch=='D'||ch=='d'||ch=='i') {
283
                        if(ch=='D')
278
                        if(ch=='D')
284
                                flags |= LONGINT;
279
                                flags |= LONGINT;
285
                        if (flags&LONGINT) {
280
                        if (flags&LONGINT) {
286
                                _ulong=va_arg(ap, long);
281
                                _ulong=va_arg(ap, long);
287
                        } else {
282
                        } else {
288
                                register int _d;
283
                                register int _d;
289
                                _d=va_arg(ap, int);
284
                                _d=va_arg(ap, int);
290
                                _ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
285
                                _ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
291
                        }
286
                        }
292
                       
287
 
293
                        if ((long)_ulong < 0) {
288
                        if ((long)_ulong < 0) {
294
                                _ulong = -_ulong;
289
                                _ulong = -_ulong;
295
                                sign = '-';
290
                                sign = '-';
296
                        }
291
                        }
297
                        base = DEC;
292
                        base = DEC;
298
                        goto number;
293
                        goto number;
299
                } else
294
                } else
300
/*             
295
/*
301
                if (ch=='n') {
296
                if (ch=='n') {
302
                        if (flags & LONGINT)
297
                        if (flags & LONGINT)
303
                                *va_arg(ap, long *) = ret;
298
                                *va_arg(ap, long *) = ret;
304
                        else if (flags & SHORTINT)
299
                        else if (flags & SHORTINT)
305
                                *va_arg(ap, short *) = ret;
300
                                *va_arg(ap, short *) = ret;
306
                        else
301
                        else
307
                                *va_arg(ap, int *) = ret;
302
                                *va_arg(ap, int *) = ret;
308
                        continue;       // no output
303
                        continue;       // no output
309
                } else
304
                } else
310
*/
305
*/
311
#ifndef LIGHTPRINTF                     
306
#ifndef LIGHTPRINTF
312
                if (ch=='O'||ch=='o') {
307
                if (ch=='O'||ch=='o') {
313
                        if (ch=='O')
308
                        if (ch=='O')
314
                                flags |= LONGINT;
309
                                flags |= LONGINT;
315
                        base = OCT;
310
                        base = OCT;
316
                        goto nosign;
311
                        goto nosign;
317
                } else if (ch=='p') {
312
                } else if (ch=='p') {
318
                        /*
313
                        /*
319
                         * ``The argument shall be a pointer to void.  The
314
                         * ``The argument shall be a pointer to void.  The
320
                         * value of the pointer is converted to a sequence
315
                         * value of the pointer is converted to a sequence
321
                         * of printable characters, in an implementation-
316
                         * of printable characters, in an implementation-
322
                         * defined manner.''
317
                         * defined manner.''
323
                         *      -- ANSI X3J11
318
                         *      -- ANSI X3J11
324
                         */
319
                         */
325
                        /* NOSTRICT */
320
                        /* NOSTRICT */
326
                        _ulong = (unsigned int)va_arg(ap, void *);
321
                        _ulong = (unsigned int)va_arg(ap, void *);
327
                        base = HEX;
322
                        base = HEX;
328
                        flags |= HEXPREFIX;
323
                        flags |= HEXPREFIX;
329
                        ch = 'x';
324
                        ch = 'x';
330
                        goto nosign;
325
                        goto nosign;
331
                } else if (ch=='s') {  // print a string from RAM
326
                } else if (ch=='s') {  // print a string from RAM
332
                        if ((cp = va_arg(ap, char *)) == NULL) {
327
                        if ((cp = va_arg(ap, char *)) == NULL) {
333
                                cp=buf;
328
                                cp=buf;
334
                                cp[0] = '(';
329
                                cp[0] = '(';
335
                                cp[1] = 'n';
330
                                cp[1] = 'n';
336
                                cp[2] = 'u';
331
                                cp[2] = 'u';
337
                                cp[4] = cp[3] = 'l';
332
                                cp[4] = cp[3] = 'l';
338
                                cp[5] = ')';
333
                                cp[5] = ')';
339
                                cp[6] = '\0';
334
                                cp[6] = '\0';
340
                        }
335
                        }
341
                        if (prec >= 0) {
336
                        if (prec >= 0) {
342
                                /*
337
                                /*
343
                                 * can't use strlen; can only look for the
338
                                 * can't use strlen; can only look for the
344
                                 * NUL in the first `prec' characters, and
339
                                 * NUL in the first `prec' characters, and
345
                                 * strlen() will go further.
340
                                 * strlen() will go further.
346
                                 */
341
                                 */
347
                                char *p = (char*)memchr(cp, 0, prec);
342
                                char *p = (char*)memchr(cp, 0, prec);
348
 
343
 
349
                                if (p != NULL) {
344
                                if (p != NULL) {
350
                                        size = p - cp;
345
                                        size = p - cp;
351
                                        if (size > prec)
346
                                        if (size > prec)
352
                                                size = prec;
347
                                                size = prec;
353
                                } else
348
                                } else
354
                                        size = prec;
349
                                        size = prec;
355
                        } else
350
                        } else
356
                                size = strlen(cp);
351
                                size = strlen(cp);
357
                        sign = '\0';
352
                        sign = '\0';
358
                } else
353
                } else
359
#endif /* LIGHTPRINTF */                        
354
#endif /* LIGHTPRINTF */
360
                if(ch=='U'||ch=='u') {
355
                if(ch=='U'||ch=='u') {
361
                        if (ch=='U')
356
                        if (ch=='U')
362
                                flags |= LONGINT;
357
                                flags |= LONGINT;
363
                        base = DEC;
358
                        base = DEC;
364
                        goto nosign;
359
                        goto nosign;
365
                } else if (ch=='X'||ch=='x') {
360
                } else if (ch=='X'||ch=='x') {
366
                        base = HEX;
361
                        base = HEX;
367
                        /* leading 0x/X only if non-zero */
362
                        /* leading 0x/X only if non-zero */
368
                        if (flags & ALT && _ulong != 0)
363
                        if (flags & ALT && _ulong != 0)
369
                                flags |= HEXPREFIX;
364
                                flags |= HEXPREFIX;
370
 
365
 
371
                        /* unsigned conversions */
366
                        /* unsigned conversions */
372
nosign:                 sign = '\0';
367
nosign:                 sign = '\0';
373
                        /*
368
                        /*
374
                         * ``... diouXx conversions ... if a precision is
369
                         * ``... diouXx conversions ... if a precision is
375
                         * specified, the 0 flag will be ignored.''
370
                         * specified, the 0 flag will be ignored.''
376
                         *      -- ANSI X3J11
371
                         *      -- ANSI X3J11
377
                         */
372
                         */
378
number: if ((dprec = prec) >= 0)
373
number: if ((dprec = prec) >= 0)
379
                                flags &= ~ZEROPAD;
374
                                flags &= ~ZEROPAD;
380
 
375
 
381
                        /*
376
                        /*
382
                         * ``The result of converting a zero value with an
377
                         * ``The result of converting a zero value with an
383
                         * explicit precision of zero is no characters.''
378
                         * explicit precision of zero is no characters.''
384
                         *      -- ANSI X3J11
379
                         *      -- ANSI X3J11
385
                         */
380
                         */
386
                        cp = buf + BUF;
381
                        cp = buf + BUF;
387
                        if (_ulong != 0 || prec != 0) {
382
                        if (_ulong != 0 || prec != 0) {
388
                                register unsigned char _d,notlastdigit;
383
                                register unsigned char _d,notlastdigit;
389
                                do {
384
                                do {
390
                                        notlastdigit=(_ulong>=base);
385
                                        notlastdigit=(_ulong>=base);
391
                                        _d = _ulong % base;
386
                                        _d = _ulong % base;
392
 
387
 
393
                                        if (_d<10) {
388
                                        if (_d<10) {
394
                                                _d+='0';
389
                                                _d+='0';
395
                                        } else {
390
                                        } else {
396
                                                _d+='a'-10;
391
                                                _d+='a'-10;
397
                                                if (ch=='X') _d&=~0x20;
392
                                                if (ch=='X') _d&=~0x20;
398
                                        }
393
                                        }
399
                                        *--cp=_d;
394
                                        *--cp=_d;
400
                                        _ulong /= base;
395
                                        _ulong /= base;
401
                                } while (notlastdigit);
396
                                } while (notlastdigit);
402
#ifndef LIGHTPRINTF
397
#ifndef LIGHTPRINTF
403
                                // handle octal leading 0 
398
                                // handle octal leading 0
404
                                if (base==OCT && flags & ALT && *cp != '0')
399
                                if (base==OCT && flags & ALT && *cp != '0')
405
                                        *--cp = '0';
400
                                        *--cp = '0';
406
#endif
401
#endif
407
                        }
402
                        }
408
 
403
 
409
                        size = buf + BUF - cp;
404
                        size = buf + BUF - cp;
410
        } else {  //default
405
        } else {  //default
411
                /* "%?" prints ?, unless ? is NUL */
406
                /* "%?" prints ?, unless ? is NUL */
412
                        if (ch == '\0')
407
                        if (ch == '\0')
413
                                goto done;
408
                                goto done;
414
                        /* pretend it was %c with argument ch */
409
                        /* pretend it was %c with argument ch */
415
                        cp = buf;
410
                        cp = buf;
416
                        *cp = ch;
411
                        *cp = ch;
417
                        size = 1;
412
                        size = 1;
418
                        sign = '\0';
413
                        sign = '\0';
419
                }
414
                }
420
 
415
 
421
                /*
416
                /*
422
                 * All reasonable formats wind up here.  At this point,
417
                 * All reasonable formats wind up here.  At this point,
423
                 * `cp' points to a string which (if not flags&LADJUST)
418
                 * `cp' points to a string which (if not flags&LADJUST)
424
                 * should be padded out to `width' places.  If
419
                 * should be padded out to `width' places.  If
425
                 * flags&ZEROPAD, it should first be prefixed by any
420
                 * flags&ZEROPAD, it should first be prefixed by any
426
                 * sign or other prefix; otherwise, it should be blank
421
                 * sign or other prefix; otherwise, it should be blank
427
                 * padded before the prefix is emitted.  After any
422
                 * padded before the prefix is emitted.  After any
428
                 * left-hand padding and prefixing, emit zeroes
423
                 * left-hand padding and prefixing, emit zeroes
429
                 * required by a decimal [diouxX] precision, then print
424
                 * required by a decimal [diouxX] precision, then print
430
                 * the string proper, then emit zeroes required by any
425
                 * the string proper, then emit zeroes required by any
431
                 * leftover floating precision; finally, if LADJUST,
426
                 * leftover floating precision; finally, if LADJUST,
432
                 * pad with blanks.
427
                 * pad with blanks.
433
                 */
428
                 */
434
 
429
 
435
                /*
430
                /*
436
                 * compute actual size, so we know how much to pad.
431
                 * compute actual size, so we know how much to pad.
437
                 */
432
                 */
438
                fieldsz = size;
433
                fieldsz = size;
439
 
434
 
440
                dpad = dprec - size;
435
                dpad = dprec - size;
441
                if (dpad < 0)
436
                if (dpad < 0)
442
                    dpad = 0;
437
                    dpad = 0;
443
 
438
 
444
                if (sign)
439
                if (sign)
445
                        fieldsz++;
440
                        fieldsz++;
446
                else if (flags & HEXPREFIX)
441
                else if (flags & HEXPREFIX)
447
                        fieldsz += 2;
442
                        fieldsz += 2;
448
                fieldsz += dpad;
443
                fieldsz += dpad;
449
 
444
 
450
                /* right-adjusting blank padding */
445
                /* right-adjusting blank padding */
451
                if ((flags & (LADJUST|ZEROPAD)) == 0)
446
                if ((flags & (LADJUST|ZEROPAD)) == 0)
452
                        PAD_SP(width - fieldsz);
447
                        PAD_SP(pPutchar, width - fieldsz);
453
 
448
 
454
                /* prefix */
449
                /* prefix */
455
                if (sign) {
450
                if (sign) {
456
                        PRINT(&sign, 1);
451
                        PRINT(pPutchar, &sign, 1);
457
                } else if (flags & HEXPREFIX) {
452
                } else if (flags & HEXPREFIX) {
458
                        ox[0] = '0';
453
                        ox[0] = '0';
459
                        ox[1] = ch;
454
                        ox[1] = ch;
460
                        PRINT(ox, 2);
455
                        PRINT(pPutchar, ox, 2);
461
                }
456
                }
462
 
457
 
463
                /* right-adjusting zero padding */
458
                /* right-adjusting zero padding */
464
                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
459
                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
465
                        PAD_0(width - fieldsz);
460
                        PAD_0(pPutchar, width - fieldsz);
466
 
461
 
467
                /* leading zeroes from decimal precision */
462
                /* leading zeroes from decimal precision */
468
                PAD_0(dpad);
463
                PAD_0(pPutchar, dpad);
469
 
464
 
470
                /* the string or number proper */
465
                /* the string or number proper */
471
                PRINT(cp, size);
466
                PRINT(pPutchar, cp, size);
472
 
467
 
473
                /* left-adjusting padding (always blank) */
468
                /* left-adjusting padding (always blank) */
474
                if (flags & LADJUST)
469
                if (flags & LADJUST)
475
                        PAD_SP(width - fieldsz);
470
                        PAD_SP(pPutchar, width - fieldsz);
476
        }
471
        }
477
done:
472
done:
478
        va_end(ap);
473
        va_end(ap);
479
}
474
}
480
 
475