~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openbios/libc/vsprintf.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * String functions for logger.
 
3
 */
 
4
 
 
5
/*
 
6
 *  linux/lib/vsprintf.c
 
7
 *
 
8
 *  Copyright (C) 1991, 1992  Linus Torvalds
 
9
 */
 
10
 
 
11
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
 
12
/*
 
13
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
 
14
 */
 
15
 
 
16
/*
 
17
 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
 
18
 * - changed to provide snprintf and vsnprintf functions
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include "libc/string.h"
 
23
#include "libc/vsprintf.h"
 
24
 
 
25
static int skip_atoi(const char **s)
 
26
{
 
27
        int i=0;
 
28
 
 
29
        while (isdigit(**s))
 
30
                i = i*10 + *((*s)++) - '0';
 
31
        return i;
 
32
}
 
33
 
 
34
#define ZEROPAD 1               /* pad with zero */
 
35
#define SIGN    2               /* unsigned/signed long */
 
36
#define PLUS    4               /* show plus */
 
37
#define SPACE   8               /* space if plus */
 
38
#define LEFT    16              /* left justified */
 
39
#define SPECIAL 32              /* 0x */
 
40
#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
 
41
 
 
42
#define do_div(n,base) ({ \
 
43
int __res; \
 
44
__res = ((unsigned long long) n) % (unsigned) base; \
 
45
n = ((unsigned long long) n) / (unsigned) base; \
 
46
__res; })
 
47
 
 
48
static int mstrlen( const char *str );
 
49
 
 
50
#ifndef PAGE_SIZE
 
51
#define PAGE_SIZE 4096
 
52
#endif
 
53
 
 
54
static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
 
55
{
 
56
        char c,sign,tmp[66];
 
57
        const char *digits;
 
58
        static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
59
        static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
60
        int i;
 
61
 
 
62
        digits = (type & LARGE) ? large_digits : small_digits;
 
63
        if (type & LEFT)
 
64
                type &= ~ZEROPAD;
 
65
        if (base < 2 || base > 36)
 
66
                return NULL;
 
67
        c = (type & ZEROPAD) ? '0' : ' ';
 
68
        sign = 0;
 
69
        if (type & SIGN) {
 
70
                if (num < 0) {
 
71
                        sign = '-';
 
72
                        num = -num;
 
73
                        size--;
 
74
                } else if (type & PLUS) {
 
75
                        sign = '+';
 
76
                        size--;
 
77
                } else if (type & SPACE) {
 
78
                        sign = ' ';
 
79
                        size--;
 
80
                }
 
81
        }
 
82
        if (type & SPECIAL) {
 
83
                if (base == 16)
 
84
                        size -= 2;
 
85
                else if (base == 8)
 
86
                        size--;
 
87
        }
 
88
        i = 0;
 
89
        if (num == 0)
 
90
                tmp[i++]='0';
 
91
        else while (num != 0)
 
92
                tmp[i++] = digits[do_div(num,base)];
 
93
        if (i > precision)
 
94
                precision = i;
 
95
        size -= precision;
 
96
        if (!(type&(ZEROPAD+LEFT))) {
 
97
                while(size-->0) {
 
98
                        if (buf <= end)
 
99
                                *buf = ' ';
 
100
                        ++buf;
 
101
                }
 
102
        }
 
103
        if (sign) {
 
104
                if (buf <= end)
 
105
                        *buf = sign;
 
106
                ++buf;
 
107
        }
 
108
        if (type & SPECIAL) {
 
109
                if (base==8) {
 
110
                        if (buf <= end)
 
111
                                *buf = '0';
 
112
                        ++buf;
 
113
                } else if (base==16) {
 
114
                        if (buf <= end)
 
115
                                *buf = '0';
 
116
                        ++buf;
 
117
                        if (buf <= end)
 
118
                                *buf = digits[33];
 
119
                        ++buf;
 
120
                }
 
121
        }
 
122
        if (!(type & LEFT)) {
 
123
                while (size-- > 0) {
 
124
                        if (buf <= end)
 
125
                                *buf = c;
 
126
                        ++buf;
 
127
                }
 
128
        }
 
129
        while (i < precision--) {
 
130
                if (buf <= end)
 
131
                        *buf = '0';
 
132
                ++buf;
 
133
        }
 
134
        while (i-- > 0) {
 
135
                if (buf <= end)
 
136
                        *buf = tmp[i];
 
137
                ++buf;
 
138
        }
 
139
        while (size-- > 0) {
 
140
                if (buf <= end)
 
141
                        *buf = ' ';
 
142
                ++buf;
 
143
        }
 
144
        return buf;
 
145
}
 
146
 
 
147
/**
 
148
* vsnprintf - Format a string and place it in a buffer
 
149
* @buf: The buffer to place the result into
 
150
* @size: The size of the buffer, including the trailing null space
 
151
* @fmt: The format string to use
 
152
* @args: Arguments for the format string
 
153
*
 
154
* Call this function if you are already dealing with a va_list.
 
155
* You probably want snprintf instead.
 
156
 */
 
157
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 
158
{
 
159
        int len;
 
160
        unsigned long long num;
 
161
        int i, base;
 
162
        char *str, *end, c;
 
163
        const char *s;
 
164
 
 
165
        int flags;              /* flags to number() */
 
166
 
 
167
        int field_width;        /* width of output field */
 
168
        int precision;          /* min. # of digits for integers; max
 
169
                                   number of chars for from string */
 
170
        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
 
171
                                /* 'z' support added 23/7/1999 S.H.    */
 
172
                                /* 'z' changed to 'Z' --davidm 1/25/99 */
 
173
 
 
174
        str = buf;
 
175
        end = buf + size - 1;
 
176
 
 
177
        if (end < buf - 1) {
 
178
                end = ((void *) -1);
 
179
                size = end - buf + 1;
 
180
        }
 
181
 
 
182
        for (; *fmt ; ++fmt) {
 
183
                if (*fmt != '%') {
 
184
                        if (str <= end)
 
185
                                *str = *fmt;
 
186
                        ++str;
 
187
                        continue;
 
188
                }
 
189
 
 
190
                /* process flags */
 
191
                flags = 0;
 
192
                repeat:
 
193
                        ++fmt;          /* this also skips first '%' */
 
194
                        switch (*fmt) {
 
195
                                case '-': flags |= LEFT; goto repeat;
 
196
                                case '+': flags |= PLUS; goto repeat;
 
197
                                case ' ': flags |= SPACE; goto repeat;
 
198
                                case '#': flags |= SPECIAL; goto repeat;
 
199
                                case '0': flags |= ZEROPAD; goto repeat;
 
200
                        }
 
201
 
 
202
                /* get field width */
 
203
                field_width = -1;
 
204
                if (isdigit(*fmt))
 
205
                        field_width = skip_atoi(&fmt);
 
206
                else if (*fmt == '*') {
 
207
                        ++fmt;
 
208
                        /* it's the next argument */
 
209
                        field_width = va_arg(args, int);
 
210
                        if (field_width < 0) {
 
211
                                field_width = -field_width;
 
212
                                flags |= LEFT;
 
213
                        }
 
214
                }
 
215
 
 
216
                /* get the precision */
 
217
                precision = -1;
 
218
                if (*fmt == '.') {
 
219
                        ++fmt;
 
220
                        if (isdigit(*fmt))
 
221
                                precision = skip_atoi(&fmt);
 
222
                        else if (*fmt == '*') {
 
223
                                ++fmt;
 
224
                                /* it's the next argument */
 
225
                                precision = va_arg(args, int);
 
226
                        }
 
227
                        if (precision < 0)
 
228
                                precision = 0;
 
229
                }
 
230
 
 
231
                /* get the conversion qualifier */
 
232
                qualifier = -1;
 
233
                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
 
234
                    *fmt =='Z' || *fmt == 'z') {
 
235
                        qualifier = *fmt;
 
236
                        ++fmt;
 
237
                        if (qualifier == 'l' && *fmt == 'l') {
 
238
                                qualifier = 'L';
 
239
                                ++fmt;
 
240
                        }
 
241
                }
 
242
 
 
243
                /* default base */
 
244
                base = 10;
 
245
 
 
246
                switch (*fmt) {
 
247
                        case 'c':
 
248
                                if (!(flags & LEFT)) {
 
249
                                        while (--field_width > 0) {
 
250
                                                if (str <= end)
 
251
                                                        *str = ' ';
 
252
                                                ++str;
 
253
                                        }
 
254
                                }
 
255
                                c = (unsigned char) va_arg(args, int);
 
256
                                if (str <= end)
 
257
                                        *str = c;
 
258
                                ++str;
 
259
                                while (--field_width > 0) {
 
260
                                        if (str <= end)
 
261
                                                *str = ' ';
 
262
                                        ++str;
 
263
                                }
 
264
                                continue;
 
265
 
 
266
                        case 's':
 
267
                                s = va_arg(args, char *);
 
268
                                if ((unsigned long)s < PAGE_SIZE)
 
269
                                        s = "<NULL>";
 
270
 
 
271
#if 0
 
272
                                len = strnlen(s, precision);
 
273
#else
 
274
                                len = mstrlen(s);
 
275
                                if( precision > len )
 
276
                                    len = precision;
 
277
#endif
 
278
                                if (!(flags & LEFT)) {
 
279
                                        while (len < field_width--) {
 
280
                                                if (str <= end)
 
281
                                                        *str = ' ';
 
282
                                                ++str;
 
283
                                        }
 
284
                                }
 
285
                                for (i = 0; i < len; ++i) {
 
286
                                        if (str <= end)
 
287
                                                *str = *s;
 
288
                                        ++str; ++s;
 
289
                                }
 
290
                                while (len < field_width--) {
 
291
                                        if (str <= end)
 
292
                                                *str = ' ';
 
293
                                        ++str;
 
294
                                }
 
295
                                continue;
 
296
 
 
297
                        case 'p':
 
298
                                if (field_width == -1) {
 
299
                                        field_width = 2*sizeof(void *);
 
300
                                        flags |= ZEROPAD;
 
301
                                }
 
302
                                str = number(str, end,
 
303
                                                (unsigned long) va_arg(args, void *),
 
304
                                                16, field_width, precision, flags);
 
305
                                continue;
 
306
 
 
307
 
 
308
                        case 'n':
 
309
                                /* FIXME:
 
310
                                * What does C99 say about the overflow case here? */
 
311
                                if (qualifier == 'l') {
 
312
                                        long * ip = va_arg(args, long *);
 
313
                                        *ip = (str - buf);
 
314
                                } else if (qualifier == 'Z' || qualifier == 'z') {
 
315
                                        size_t * ip = va_arg(args, size_t *);
 
316
                                        *ip = (str - buf);
 
317
                                } else {
 
318
                                        int * ip = va_arg(args, int *);
 
319
                                        *ip = (str - buf);
 
320
                                }
 
321
                                continue;
 
322
 
 
323
                        case '%':
 
324
                                if (str <= end)
 
325
                                        *str = '%';
 
326
                                ++str;
 
327
                                continue;
 
328
 
 
329
                                /* integer number formats - set up the flags and "break" */
 
330
                        case 'o':
 
331
                                base = 8;
 
332
                                break;
 
333
 
 
334
                        case 'X':
 
335
                                flags |= LARGE;
 
336
                        case 'x':
 
337
                                base = 16;
 
338
                                break;
 
339
 
 
340
                        case 'd':
 
341
                        case 'i':
 
342
                                flags |= SIGN;
 
343
                        case 'u':
 
344
                                break;
 
345
 
 
346
                        default:
 
347
                                if (str <= end)
 
348
                                        *str = '%';
 
349
                                ++str;
 
350
                                if (*fmt) {
 
351
                                        if (str <= end)
 
352
                                                *str = *fmt;
 
353
                                        ++str;
 
354
                                } else {
 
355
                                        --fmt;
 
356
                                }
 
357
                                continue;
 
358
                }
 
359
                if (qualifier == 'L')
 
360
                        num = va_arg(args, long long);
 
361
                else if (qualifier == 'l') {
 
362
                        num = va_arg(args, unsigned long);
 
363
                        if (flags & SIGN)
 
364
                                num = (signed long) num;
 
365
                } else if (qualifier == 'Z' || qualifier == 'z') {
 
366
                        num = va_arg(args, size_t);
 
367
                } else if (qualifier == 'h') {
 
368
                        num = (unsigned short) va_arg(args, int);
 
369
                        if (flags & SIGN)
 
370
                                num = (signed short) num;
 
371
                } else {
 
372
                        num = va_arg(args, unsigned int);
 
373
                        if (flags & SIGN)
 
374
                                num = (signed int) num;
 
375
                }
 
376
                str = number(str, end, num, base,
 
377
                                field_width, precision, flags);
 
378
        }
 
379
        if (str <= end)
 
380
                *str = '\0';
 
381
        else if (size > 0)
 
382
                /* don't write out a null byte if the buf size is zero */
 
383
                *end = '\0';
 
384
        /* the trailing null byte doesn't count towards the total
 
385
        * ++str;
 
386
        */
 
387
        return str-buf;
 
388
}
 
389
 
 
390
/**
 
391
 * snprintf - Format a string and place it in a buffer
 
392
 * @buf: The buffer to place the result into
 
393
 * @size: The size of the buffer, including the trailing null space
 
394
 * @fmt: The format string to use
 
395
 * @...: Arguments for the format string
 
396
 */
 
397
int snprintf(char * buf, size_t size, const char *fmt, ...)
 
398
{
 
399
        va_list args;
 
400
        int i;
 
401
 
 
402
        va_start(args, fmt);
 
403
        i=vsnprintf(buf,size,fmt,args);
 
404
        va_end(args);
 
405
        return i;
 
406
}
 
407
 
 
408
/**
 
409
 * vsprintf - Format a string and place it in a buffer
 
410
 * @buf: The buffer to place the result into
 
411
 * @fmt: The format string to use
 
412
 * @args: Arguments for the format string
 
413
 *
 
414
 * Call this function if you are already dealing with a va_list.
 
415
 * You probably want sprintf instead.
 
416
 */
 
417
int vsprintf(char *buf, const char *fmt, va_list args)
 
418
{
 
419
        return vsnprintf(buf, (~0U)>>1, fmt, args);
 
420
}
 
421
 
 
422
 
 
423
/**
 
424
 * sprintf - Format a string and place it in a buffer
 
425
 * @buf: The buffer to place the result into
 
426
 * @fmt: The format string to use
 
427
 * @...: Arguments for the format string
 
428
 */
 
429
int sprintf(char * buf, const char *fmt, ...)
 
430
{
 
431
        va_list args;
 
432
        int i;
 
433
 
 
434
        va_start(args, fmt);
 
435
        i=vsprintf(buf,fmt,args);
 
436
        va_end(args);
 
437
        return i;
 
438
}
 
439
 
 
440
static int mstrlen( const char *str )
 
441
{
 
442
        int i=0;
 
443
        if( str == NULL )
 
444
                return 0;
 
445
        while( *str++ )
 
446
                i++;
 
447
        return i;
 
448
}