Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 *  linux/lib/vsprintf.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8
/*
9
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10
 */
11
 
12
/*
13
 * Fri Jul 13 2001 Crutcher Dunnavant 
14
 * - changed to provide snprintf and vsnprintf functions
15
 * So Feb  1 16:51:32 CET 2004 Juergen Quade 
16
 * - scnprintf and vscnprintf
17
 */
18
 
19
#define likely(x)       __builtin_expect(!!(x), 1)
20
#define unlikely(x)     __builtin_expect(!!(x), 0)
21
 
22
#include 
23
#include 
24
#include 
25
#include 
26
 
27
//#include 
28
//#include 
29
//#include 
30
//#include 
31
//#include 
32
//#include 
33
 
34
//#include       /* for PAGE_SIZE */
35
//#include 
36
//#include   /* for dereference_function_descriptor() */
37
 
38
#define do_div(n, base)                     \
39
({                              \
40
    unsigned long __upper, __low, __high, __mod, __base;    \
41
    __base = (base);                    \
42
    asm("":"=a" (__low), "=d" (__high) : "A" (n));      \
43
    __upper = __high;                   \
44
    if (__high) {                       \
45
        __upper = __high % (__base);            \
46
        __high = __high / (__base);         \
47
    }                           \
48
    asm("divl %2":"=a" (__low), "=d" (__mod)        \
49
        : "rm" (__base), "0" (__low), "1" (__upper));   \
50
    asm("":"=A" (n) : "a" (__low), "d" (__high));       \
51
    __mod;                          \
52
})
53
 
54
#define EPERM        1  /* Operation not permitted */
55
#define ENOENT       2  /* No such file or directory */
56
#define ESRCH        3  /* No such process */
57
#define EINTR        4  /* Interrupted system call */
58
#define EIO          5  /* I/O error */
59
#define ENXIO        6  /* No such device or address */
60
#define E2BIG        7  /* Argument list too long */
61
#define ENOEXEC      8  /* Exec format error */
62
#define EBADF        9  /* Bad file number */
63
#define ECHILD      10  /* No child processes */
64
#define EAGAIN      11  /* Try again */
65
#define ENOMEM      12  /* Out of memory */
66
#define EACCES      13  /* Permission denied */
67
#define EFAULT      14  /* Bad address */
68
#define ENOTBLK     15  /* Block device required */
69
#define EBUSY       16  /* Device or resource busy */
70
#define EEXIST      17  /* File exists */
71
#define EXDEV       18  /* Cross-device link */
72
#define ENODEV      19  /* No such device */
73
#define ENOTDIR     20  /* Not a directory */
74
#define EISDIR      21  /* Is a directory */
75
#define EINVAL      22  /* Invalid argument */
76
#define ENFILE      23  /* File table overflow */
77
#define EMFILE      24  /* Too many open files */
78
#define ENOTTY      25  /* Not a typewriter */
79
#define ETXTBSY     26  /* Text file busy */
80
#define EFBIG       27  /* File too large */
81
#define ENOSPC      28  /* No space left on device */
82
#define ESPIPE      29  /* Illegal seek */
83
#define EROFS       30  /* Read-only file system */
84
#define EMLINK      31  /* Too many links */
85
#define EPIPE       32  /* Broken pipe */
86
#define EDOM        33  /* Math argument out of domain of func */
87
#define ERANGE      34  /* Math result not representable */
88
 
89
#define PAGE_SIZE 4096
90
 
91
/* Works only for digits and letters, but small and fast */
92
#define TOLOWER(x) ((x) | 0x20)
93
 
94
static unsigned int simple_guess_base(const char *cp)
95
{
96
	if (cp[0] == '0') {
97
		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
98
			return 16;
99
		else
100
			return 8;
101
	} else {
102
		return 10;
103
	}
104
}
105
 
106
/**
107
 * simple_strtoul - convert a string to an unsigned long
108
 * @cp: The start of the string
109
 * @endp: A pointer to the end of the parsed string will be placed here
110
 * @base: The number base to use
111
 */
112
unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
113
{
114
	unsigned long result = 0;
115
 
116
	if (!base)
117
		base = simple_guess_base(cp);
118
 
119
	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
120
		cp += 2;
121
 
122
	while (isxdigit(*cp)) {
123
		unsigned int value;
124
 
125
		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
126
		if (value >= base)
127
			break;
128
		result = result * base + value;
129
		cp++;
130
	}
131
 
132
	if (endp)
133
		*endp = (char *)cp;
134
	return result;
135
}
136
 
137
/**
138
 * simple_strtol - convert a string to a signed long
139
 * @cp: The start of the string
140
 * @endp: A pointer to the end of the parsed string will be placed here
141
 * @base: The number base to use
142
 */
143
long simple_strtol(const char *cp, char **endp, unsigned int base)
144
{
145
	if(*cp == '-')
146
		return -simple_strtoul(cp + 1, endp, base);
147
	return simple_strtoul(cp, endp, base);
148
}
149
 
150
/**
151
 * simple_strtoull - convert a string to an unsigned long long
152
 * @cp: The start of the string
153
 * @endp: A pointer to the end of the parsed string will be placed here
154
 * @base: The number base to use
155
 */
156
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
157
{
158
	unsigned long long result = 0;
159
 
160
	if (!base)
161
		base = simple_guess_base(cp);
162
 
163
	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
164
		cp += 2;
165
 
166
	while (isxdigit(*cp)) {
167
		unsigned int value;
168
 
169
		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
170
		if (value >= base)
171
			break;
172
		result = result * base + value;
173
		cp++;
174
	}
175
 
176
	if (endp)
177
		*endp = (char *)cp;
178
	return result;
179
}
180
 
181
/**
182
 * simple_strtoll - convert a string to a signed long long
183
 * @cp: The start of the string
184
 * @endp: A pointer to the end of the parsed string will be placed here
185
 * @base: The number base to use
186
 */
187
long long simple_strtoll(const char *cp, char **endp, unsigned int base)
188
{
189
	if(*cp=='-')
190
		return -simple_strtoull(cp + 1, endp, base);
191
	return simple_strtoull(cp, endp, base);
192
}
193
 
194
/**
195
 * strict_strtoul - convert a string to an unsigned long strictly
196
 * @cp: The string to be converted
197
 * @base: The number base to use
198
 * @res: The converted result value
199
 *
200
 * strict_strtoul converts a string to an unsigned long only if the
201
 * string is really an unsigned long string, any string containing
202
 * any invalid char at the tail will be rejected and -EINVAL is returned,
203
 * only a newline char at the tail is acceptible because people generally
204
 * change a module parameter in the following way:
205
 *
206
 * 	echo 1024 > /sys/module/e1000/parameters/copybreak
207
 *
208
 * echo will append a newline to the tail.
209
 *
210
 * It returns 0 if conversion is successful and *res is set to the converted
211
 * value, otherwise it returns -EINVAL and *res is set to 0.
212
 *
213
 * simple_strtoul just ignores the successive invalid characters and
214
 * return the converted value of prefix part of the string.
215
 */
216
int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
217
{
218
	char *tail;
219
	unsigned long val;
220
	size_t len;
221
 
222
	*res = 0;
223
	len = strlen(cp);
224
	if (len == 0)
225
		return -EINVAL;
226
 
227
	val = simple_strtoul(cp, &tail, base);
228
	if (tail == cp)
229
		return -EINVAL;
230
	if ((*tail == '\0') ||
231
		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
232
		*res = val;
233
		return 0;
234
	}
235
 
236
	return -EINVAL;
237
}
238
 
239
/**
240
 * strict_strtol - convert a string to a long strictly
241
 * @cp: The string to be converted
242
 * @base: The number base to use
243
 * @res: The converted result value
244
 *
245
 * strict_strtol is similiar to strict_strtoul, but it allows the first
246
 * character of a string is '-'.
247
 *
248
 * It returns 0 if conversion is successful and *res is set to the converted
249
 * value, otherwise it returns -EINVAL and *res is set to 0.
250
 */
251
int strict_strtol(const char *cp, unsigned int base, long *res)
252
{
253
	int ret;
254
	if (*cp == '-') {
255
		ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
256
		if (!ret)
257
			*res = -(*res);
258
	} else {
259
		ret = strict_strtoul(cp, base, (unsigned long *)res);
260
	}
261
 
262
	return ret;
263
}
264
 
265
/**
266
 * strict_strtoull - convert a string to an unsigned long long strictly
267
 * @cp: The string to be converted
268
 * @base: The number base to use
269
 * @res: The converted result value
270
 *
271
 * strict_strtoull converts a string to an unsigned long long only if the
272
 * string is really an unsigned long long string, any string containing
273
 * any invalid char at the tail will be rejected and -EINVAL is returned,
274
 * only a newline char at the tail is acceptible because people generally
275
 * change a module parameter in the following way:
276
 *
277
 * 	echo 1024 > /sys/module/e1000/parameters/copybreak
278
 *
279
 * echo will append a newline to the tail of the string.
280
 *
281
 * It returns 0 if conversion is successful and *res is set to the converted
282
 * value, otherwise it returns -EINVAL and *res is set to 0.
283
 *
284
 * simple_strtoull just ignores the successive invalid characters and
285
 * return the converted value of prefix part of the string.
286
 */
287
int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
288
{
289
	char *tail;
290
	unsigned long long val;
291
	size_t len;
292
 
293
	*res = 0;
294
	len = strlen(cp);
295
	if (len == 0)
296
		return -EINVAL;
297
 
298
	val = simple_strtoull(cp, &tail, base);
299
	if (tail == cp)
300
		return -EINVAL;
301
	if ((*tail == '\0') ||
302
		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
303
		*res = val;
304
		return 0;
305
	}
306
 
307
	return -EINVAL;
308
}
309
 
310
/**
311
 * strict_strtoll - convert a string to a long long strictly
312
 * @cp: The string to be converted
313
 * @base: The number base to use
314
 * @res: The converted result value
315
 *
316
 * strict_strtoll is similiar to strict_strtoull, but it allows the first
317
 * character of a string is '-'.
318
 *
319
 * It returns 0 if conversion is successful and *res is set to the converted
320
 * value, otherwise it returns -EINVAL and *res is set to 0.
321
 */
322
int strict_strtoll(const char *cp, unsigned int base, long long *res)
323
{
324
	int ret;
325
	if (*cp == '-') {
326
		ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
327
		if (!ret)
328
			*res = -(*res);
329
	} else {
330
		ret = strict_strtoull(cp, base, (unsigned long long *)res);
331
	}
332
 
333
	return ret;
334
}
335
 
336
static int skip_atoi(const char **s)
337
{
338
	int i=0;
339
 
340
	while (isdigit(**s))
341
		i = i*10 + *((*s)++) - '0';
342
	return i;
343
}
344
 
345
/* Decimal conversion is by far the most typical, and is used
346
 * for /proc and /sys data. This directly impacts e.g. top performance
347
 * with many processes running. We optimize it for speed
348
 * using code from
349
 * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
350
 * (with permission from the author, Douglas W. Jones). */
351
 
352
/* Formats correctly any integer in [0,99999].
353
 * Outputs from one to five digits depending on input.
354
 * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
355
static char* put_dec_trunc(char *buf, unsigned q)
356
{
357
	unsigned d3, d2, d1, d0;
358
	d1 = (q>>4) & 0xf;
359
	d2 = (q>>8) & 0xf;
360
	d3 = (q>>12);
361
 
362
	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
363
	q = (d0 * 0xcd) >> 11;
364
	d0 = d0 - 10*q;
365
	*buf++ = d0 + '0'; /* least significant digit */
366
	d1 = q + 9*d3 + 5*d2 + d1;
367
	if (d1 != 0) {
368
		q = (d1 * 0xcd) >> 11;
369
		d1 = d1 - 10*q;
370
		*buf++ = d1 + '0'; /* next digit */
371
 
372
		d2 = q + 2*d2;
373
		if ((d2 != 0) || (d3 != 0)) {
374
			q = (d2 * 0xd) >> 7;
375
			d2 = d2 - 10*q;
376
			*buf++ = d2 + '0'; /* next digit */
377
 
378
			d3 = q + 4*d3;
379
			if (d3 != 0) {
380
				q = (d3 * 0xcd) >> 11;
381
				d3 = d3 - 10*q;
382
				*buf++ = d3 + '0';  /* next digit */
383
				if (q != 0)
384
					*buf++ = q + '0';  /* most sign. digit */
385
			}
386
		}
387
	}
388
	return buf;
389
}
390
/* Same with if's removed. Always emits five digits */
391
static char* put_dec_full(char *buf, unsigned q)
392
{
393
	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
394
	/* but anyway, gcc produces better code with full-sized ints */
395
	unsigned d3, d2, d1, d0;
396
	d1 = (q>>4) & 0xf;
397
	d2 = (q>>8) & 0xf;
398
	d3 = (q>>12);
399
 
400
	/* Possible ways to approx. divide by 10 */
401
	/* gcc -O2 replaces multiply with shifts and adds */
402
	// (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
403
	// (x * 0x67) >> 10:  1100111
404
	// (x * 0x34) >> 9:    110100 - same
405
	// (x * 0x1a) >> 8:     11010 - same
406
	// (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
407
 
408
	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
409
	q = (d0 * 0xcd) >> 11;
410
	d0 = d0 - 10*q;
411
	*buf++ = d0 + '0';
412
	d1 = q + 9*d3 + 5*d2 + d1;
413
		q = (d1 * 0xcd) >> 11;
414
		d1 = d1 - 10*q;
415
		*buf++ = d1 + '0';
416
 
417
		d2 = q + 2*d2;
418
			q = (d2 * 0xd) >> 7;
419
			d2 = d2 - 10*q;
420
			*buf++ = d2 + '0';
421
 
422
			d3 = q + 4*d3;
423
				q = (d3 * 0xcd) >> 11; /* - shorter code */
424
				/* q = (d3 * 0x67) >> 10; - would also work */
425
				d3 = d3 - 10*q;
426
				*buf++ = d3 + '0';
427
					*buf++ = q + '0';
428
	return buf;
429
}
430
/* No inlining helps gcc to use registers better */
431
static char* put_dec(char *buf, unsigned long long num)
432
{
433
	while (1) {
434
		unsigned rem;
435
		if (num < 100000)
436
			return put_dec_trunc(buf, num);
437
		rem = do_div(num, 100000);
438
		buf = put_dec_full(buf, rem);
439
	}
440
}
441
 
442
#define ZEROPAD	1		/* pad with zero */
443
#define SIGN	2		/* unsigned/signed long */
444
#define PLUS	4		/* show plus */
445
#define SPACE	8		/* space if plus */
446
#define LEFT	16		/* left justified */
447
#define SMALL	32		/* Must be 32 == 0x20 */
448
#define SPECIAL	64		/* 0x */
449
 
450
enum format_type {
451
	FORMAT_TYPE_NONE, /* Just a string part */
452
	FORMAT_TYPE_WIDTH,
453
	FORMAT_TYPE_PRECISION,
454
	FORMAT_TYPE_CHAR,
455
	FORMAT_TYPE_STR,
456
	FORMAT_TYPE_PTR,
457
	FORMAT_TYPE_PERCENT_CHAR,
458
	FORMAT_TYPE_INVALID,
459
	FORMAT_TYPE_LONG_LONG,
460
	FORMAT_TYPE_ULONG,
461
	FORMAT_TYPE_LONG,
462
	FORMAT_TYPE_UBYTE,
463
	FORMAT_TYPE_BYTE,
464
	FORMAT_TYPE_USHORT,
465
	FORMAT_TYPE_SHORT,
466
	FORMAT_TYPE_UINT,
467
	FORMAT_TYPE_INT,
468
	FORMAT_TYPE_NRCHARS,
469
	FORMAT_TYPE_SIZE_T,
470
	FORMAT_TYPE_PTRDIFF
471
};
472
 
473
struct printf_spec {
474
	enum format_type	type;
475
	int			flags;		/* flags to number() */
476
	int			field_width;	/* width of output field */
477
	int			base;
478
	int			precision;	/* # of digits/chars */
479
	int			qualifier;
480
};
481
 
482
static char *number(char *buf, char *end, unsigned long long num,
483
			struct printf_spec spec)
484
{
485
	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
486
	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
487
 
488
	char tmp[66];
489
	char sign;
490
	char locase;
491
	int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
492
	int i;
493
 
494
	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
495
	 * produces same digits or (maybe lowercased) letters */
496
	locase = (spec.flags & SMALL);
497
	if (spec.flags & LEFT)
498
		spec.flags &= ~ZEROPAD;
499
	sign = 0;
500
	if (spec.flags & SIGN) {
501
		if ((signed long long) num < 0) {
502
			sign = '-';
503
			num = - (signed long long) num;
504
			spec.field_width--;
505
		} else if (spec.flags & PLUS) {
506
			sign = '+';
507
			spec.field_width--;
508
		} else if (spec.flags & SPACE) {
509
			sign = ' ';
510
			spec.field_width--;
511
		}
512
	}
513
	if (need_pfx) {
514
		spec.field_width--;
515
		if (spec.base == 16)
516
			spec.field_width--;
517
	}
518
 
519
	/* generate full string in tmp[], in reverse order */
520
	i = 0;
521
	if (num == 0)
522
		tmp[i++] = '0';
523
	/* Generic code, for any base:
524
	else do {
525
		tmp[i++] = (digits[do_div(num,base)] | locase);
526
	} while (num != 0);
527
	*/
528
	else if (spec.base != 10) { /* 8 or 16 */
529
		int mask = spec.base - 1;
530
		int shift = 3;
531
		if (spec.base == 16) shift = 4;
532
		do {
533
			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
534
			num >>= shift;
535
		} while (num);
536
	} else { /* base 10 */
537
		i = put_dec(tmp, num) - tmp;
538
	}
539
 
540
	/* printing 100 using %2d gives "100", not "00" */
541
	if (i > spec.precision)
542
		spec.precision = i;
543
	/* leading space padding */
544
	spec.field_width -= spec.precision;
545
	if (!(spec.flags & (ZEROPAD+LEFT))) {
546
		while(--spec.field_width >= 0) {
547
			if (buf < end)
548
				*buf = ' ';
549
			++buf;
550
		}
551
	}
552
	/* sign */
553
	if (sign) {
554
		if (buf < end)
555
			*buf = sign;
556
		++buf;
557
	}
558
	/* "0x" / "0" prefix */
559
	if (need_pfx) {
560
		if (buf < end)
561
			*buf = '0';
562
		++buf;
563
		if (spec.base == 16) {
564
			if (buf < end)
565
				*buf = ('X' | locase);
566
			++buf;
567
		}
568
	}
569
	/* zero or space padding */
570
	if (!(spec.flags & LEFT)) {
571
		char c = (spec.flags & ZEROPAD) ? '0' : ' ';
572
		while (--spec.field_width >= 0) {
573
			if (buf < end)
574
				*buf = c;
575
			++buf;
576
		}
577
	}
578
	/* hmm even more zero padding? */
579
	while (i <= --spec.precision) {
580
		if (buf < end)
581
			*buf = '0';
582
		++buf;
583
	}
584
	/* actual digits of result */
585
	while (--i >= 0) {
586
		if (buf < end)
587
			*buf = tmp[i];
588
		++buf;
589
	}
590
	/* trailing space padding */
591
	while (--spec.field_width >= 0) {
592
		if (buf < end)
593
			*buf = ' ';
594
		++buf;
595
	}
596
	return buf;
597
}
598
 
599
static char *string(char *buf, char *end, char *s, struct printf_spec spec)
600
{
601
	int len, i;
602
 
603
	if ((unsigned long)s < PAGE_SIZE)
604
		s = "";
605
 
606
	len = strnlen(s, spec.precision);
607
 
608
	if (!(spec.flags & LEFT)) {
609
		while (len < spec.field_width--) {
610
			if (buf < end)
611
				*buf = ' ';
612
			++buf;
613
		}
614
	}
615
	for (i = 0; i < len; ++i) {
616
		if (buf < end)
617
			*buf = *s;
618
		++buf; ++s;
619
	}
620
	while (len < spec.field_width--) {
621
		if (buf < end)
622
			*buf = ' ';
623
		++buf;
624
	}
625
	return buf;
626
}
627
 
628
 
629
/*
630
 * Show a '%p' thing.
631
 */
632
static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
633
			struct printf_spec spec)
634
{
635
	if (!ptr)
636
		return string(buf, end, "(null)", spec);
637
 
638
    spec.flags |= SMALL;
639
	if (spec.field_width == -1) {
640
		spec.field_width = 2*sizeof(void *);
641
		spec.flags |= ZEROPAD;
642
	}
643
	spec.base = 16;
644
 
645
	return number(buf, end, (unsigned long) ptr, spec);
646
}
647
 
648
/*
649
 * Helper function to decode printf style format.
650
 * Each call decode a token from the format and return the
651
 * number of characters read (or likely the delta where it wants
652
 * to go on the next call).
653
 * The decoded token is returned through the parameters
654
 *
655
 * 'h', 'l', or 'L' for integer fields
656
 * 'z' support added 23/7/1999 S.H.
657
 * 'z' changed to 'Z' --davidm 1/25/99
658
 * 't' added for ptrdiff_t
659
 *
660
 * @fmt: the format string
661
 * @type of the token returned
662
 * @flags: various flags such as +, -, # tokens..
663
 * @field_width: overwritten width
664
 * @base: base of the number (octal, hex, ...)
665
 * @precision: precision of a number
666
 * @qualifier: qualifier of a number (long, size_t, ...)
667
 */
668
static int format_decode(const char *fmt, struct printf_spec *spec)
669
{
670
	const char *start = fmt;
671
 
672
	/* we finished early by reading the field width */
673
	if (spec->type == FORMAT_TYPE_WIDTH) {
674
		if (spec->field_width < 0) {
675
			spec->field_width = -spec->field_width;
676
			spec->flags |= LEFT;
677
		}
678
		spec->type = FORMAT_TYPE_NONE;
679
		goto precision;
680
	}
681
 
682
	/* we finished early by reading the precision */
683
	if (spec->type == FORMAT_TYPE_PRECISION) {
684
		if (spec->precision < 0)
685
			spec->precision = 0;
686
 
687
		spec->type = FORMAT_TYPE_NONE;
688
		goto qualifier;
689
	}
690
 
691
	/* By default */
692
	spec->type = FORMAT_TYPE_NONE;
693
 
694
	for (; *fmt ; ++fmt) {
695
		if (*fmt == '%')
696
			break;
697
	}
698
 
699
	/* Return the current non-format string */
700
	if (fmt != start || !*fmt)
701
		return fmt - start;
702
 
703
	/* Process flags */
704
	spec->flags = 0;
705
 
706
	while (1) { /* this also skips first '%' */
707
        int found = 1;
708
 
709
		++fmt;
710
 
711
		switch (*fmt) {
712
		case '-': spec->flags |= LEFT;    break;
713
		case '+': spec->flags |= PLUS;    break;
714
		case ' ': spec->flags |= SPACE;   break;
715
		case '#': spec->flags |= SPECIAL; break;
716
		case '0': spec->flags |= ZEROPAD; break;
717
        default:  found = 0;
718
		}
719
 
720
		if (!found)
721
			break;
722
	}
723
 
724
	/* get field width */
725
	spec->field_width = -1;
726
 
727
	if (isdigit(*fmt))
728
		spec->field_width = skip_atoi(&fmt);
729
	else if (*fmt == '*') {
730
		/* it's the next argument */
731
		spec->type = FORMAT_TYPE_WIDTH;
732
		return ++fmt - start;
733
	}
734
 
735
precision:
736
	/* get the precision */
737
	spec->precision = -1;
738
	if (*fmt == '.') {
739
		++fmt;
740
		if (isdigit(*fmt)) {
741
			spec->precision = skip_atoi(&fmt);
742
			if (spec->precision < 0)
743
				spec->precision = 0;
744
		} else if (*fmt == '*') {
745
			/* it's the next argument */
746
			spec->type = FORMAT_TYPE_PRECISION;
747
			return ++fmt - start;
748
		}
749
	}
750
 
751
qualifier:
752
	/* get the conversion qualifier */
753
	spec->qualifier = -1;
754
	if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
755
	    *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
756
		spec->qualifier = *fmt++;
757
		if (unlikely(spec->qualifier == *fmt)) {
758
			if (spec->qualifier == 'l') {
759
				spec->qualifier = 'L';
760
				++fmt;
761
			} else if (spec->qualifier == 'h') {
762
				spec->qualifier = 'H';
763
				++fmt;
764
			}
765
		}
766
	}
767
 
768
	/* default base */
769
	spec->base = 10;
770
	switch (*fmt) {
771
	case 'c':
772
		spec->type = FORMAT_TYPE_CHAR;
773
		return ++fmt - start;
774
 
775
	case 's':
776
		spec->type = FORMAT_TYPE_STR;
777
		return ++fmt - start;
778
 
779
	case 'p':
780
		spec->type = FORMAT_TYPE_PTR;
781
		return fmt - start;
782
		/* skip alnum */
783
 
784
	case 'n':
785
		spec->type = FORMAT_TYPE_NRCHARS;
786
		return ++fmt - start;
787
 
788
	case '%':
789
		spec->type = FORMAT_TYPE_PERCENT_CHAR;
790
		return ++fmt - start;
791
 
792
	/* integer number formats - set up the flags and "break" */
793
	case 'o':
794
		spec->base = 8;
795
		break;
796
 
797
	case 'x':
798
		spec->flags |= SMALL;
799
 
800
	case 'X':
801
		spec->base = 16;
802
		break;
803
 
804
	case 'd':
805
	case 'i':
806
		spec->flags |= SIGN;
807
	case 'u':
808
		break;
809
 
810
	default:
811
		spec->type = FORMAT_TYPE_INVALID;
812
		return fmt - start;
813
	}
814
 
815
	if (spec->qualifier == 'L')
816
		spec->type = FORMAT_TYPE_LONG_LONG;
817
	else if (spec->qualifier == 'l') {
818
		if (spec->flags & SIGN)
819
			spec->type = FORMAT_TYPE_LONG;
820
		else
821
			spec->type = FORMAT_TYPE_ULONG;
822
	} else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
823
		spec->type = FORMAT_TYPE_SIZE_T;
824
	} else if (spec->qualifier == 't') {
825
		spec->type = FORMAT_TYPE_PTRDIFF;
826
	} else if (spec->qualifier == 'H') {
827
		if (spec->flags & SIGN)
828
			spec->type = FORMAT_TYPE_BYTE;
829
		else
830
			spec->type = FORMAT_TYPE_UBYTE;
831
	} else if (spec->qualifier == 'h') {
832
		if (spec->flags & SIGN)
833
			spec->type = FORMAT_TYPE_SHORT;
834
		else
835
			spec->type = FORMAT_TYPE_USHORT;
836
	} else {
837
		if (spec->flags & SIGN)
838
			spec->type = FORMAT_TYPE_INT;
839
		else
840
			spec->type = FORMAT_TYPE_UINT;
841
	}
842
 
843
	return ++fmt - start;
844
}
845
 
846
/**
847
 * vsnprintf - Format a string and place it in a buffer
848
 * @buf: The buffer to place the result into
849
 * @size: The size of the buffer, including the trailing null space
850
 * @fmt: The format string to use
851
 * @args: Arguments for the format string
852
 *
853
 *
854
 * The return value is the number of characters which would
855
 * be generated for the given input, excluding the trailing
856
 * '\0', as per ISO C99. If you want to have the exact
857
 * number of characters written into @buf as return value
858
 * (not including the trailing '\0'), use vscnprintf(). If the
859
 * return is greater than or equal to @size, the resulting
860
 * string is truncated.
861
 *
862
 * Call this function if you are already dealing with a va_list.
863
 * You probably want snprintf() instead.
864
 */
865
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
866
{
867
	unsigned long long num;
868
	char *str, *end, c;
869
	int read;
870
	struct printf_spec spec = {0};
871
 
872
	/* Reject out-of-range values early.  Large positive sizes are
873
	   used for unknown buffer sizes. */
874
	if (unlikely((int) size < 0)) {
875
		/* There can be only one.. */
876
		static char warn = 1;
877
//       WARN_ON(warn);
878
		warn = 0;
879
		return 0;
880
	}
881
 
882
	str = buf;
883
	end = buf + size;
884
 
885
	/* Make sure end is always >= buf */
886
	if (end < buf) {
887
		end = ((void *)-1);
888
		size = end - buf;
889
	}
890
 
891
	while (*fmt) {
892
		const char *old_fmt = fmt;
893
 
894
		read = format_decode(fmt, &spec);
895
 
896
		fmt += read;
897
 
898
		switch (spec.type) {
899
		case FORMAT_TYPE_NONE: {
900
			int copy = read;
901
			if (str < end) {
902
				if (copy > end - str)
903
					copy = end - str;
904
				memcpy(str, old_fmt, copy);
905
			}
906
			str += read;
907
			break;
908
		}
909
 
910
		case FORMAT_TYPE_WIDTH:
911
			spec.field_width = va_arg(args, int);
912
			break;
913
 
914
		case FORMAT_TYPE_PRECISION:
915
			spec.precision = va_arg(args, int);
916
			break;
917
 
918
		case FORMAT_TYPE_CHAR:
919
			if (!(spec.flags & LEFT)) {
920
				while (--spec.field_width > 0) {
921
					if (str < end)
922
						*str = ' ';
923
					++str;
924
 
925
				}
926
			}
927
			c = (unsigned char) va_arg(args, int);
928
			if (str < end)
929
				*str = c;
930
			++str;
931
			while (--spec.field_width > 0) {
932
				if (str < end)
933
					*str = ' ';
934
				++str;
935
			}
936
			break;
937
 
938
		case FORMAT_TYPE_STR:
939
			str = string(str, end, va_arg(args, char *), spec);
940
			break;
941
 
942
		case FORMAT_TYPE_PTR:
943
			str = pointer(fmt+1, str, end, va_arg(args, void *),
944
				      spec);
945
			while (isalnum(*fmt))
946
				fmt++;
947
			break;
948
 
949
		case FORMAT_TYPE_PERCENT_CHAR:
950
			if (str < end)
951
				*str = '%';
952
			++str;
953
			break;
954
 
955
		case FORMAT_TYPE_INVALID:
956
			if (str < end)
957
				*str = '%';
958
			++str;
959
			break;
960
 
961
		case FORMAT_TYPE_NRCHARS: {
962
			int qualifier = spec.qualifier;
963
 
964
			if (qualifier == 'l') {
965
				long *ip = va_arg(args, long *);
966
				*ip = (str - buf);
967
			} else if (qualifier == 'Z' ||
968
					qualifier == 'z') {
969
				size_t *ip = va_arg(args, size_t *);
970
				*ip = (str - buf);
971
			} else {
972
				int *ip = va_arg(args, int *);
973
				*ip = (str - buf);
974
			}
975
			break;
976
		}
977
 
978
		default:
979
			switch (spec.type) {
980
			case FORMAT_TYPE_LONG_LONG:
981
				num = va_arg(args, long long);
982
				break;
983
			case FORMAT_TYPE_ULONG:
984
				num = va_arg(args, unsigned long);
985
				break;
986
			case FORMAT_TYPE_LONG:
987
				num = va_arg(args, long);
988
				break;
989
			case FORMAT_TYPE_SIZE_T:
990
				num = va_arg(args, size_t);
991
				break;
992
//           case FORMAT_TYPE_PTRDIFF:
993
//               num = va_arg(args, ptrdiff_t);
994
//               break;
995
			case FORMAT_TYPE_UBYTE:
996
				num = (unsigned char) va_arg(args, int);
997
				break;
998
			case FORMAT_TYPE_BYTE:
999
				num = (signed char) va_arg(args, int);
1000
				break;
1001
			case FORMAT_TYPE_USHORT:
1002
				num = (unsigned short) va_arg(args, int);
1003
				break;
1004
			case FORMAT_TYPE_SHORT:
1005
				num = (short) va_arg(args, int);
1006
				break;
1007
			case FORMAT_TYPE_INT:
1008
				num = (int) va_arg(args, int);
1009
				break;
1010
			default:
1011
				num = va_arg(args, unsigned int);
1012
			}
1013
 
1014
			str = number(str, end, num, spec);
1015
		}
1016
	}
1017
 
1018
	if (size > 0) {
1019
		if (str < end)
1020
			*str = '\0';
1021
		else
1022
			end[-1] = '\0';
1023
	}
1024
 
1025
	/* the trailing null byte doesn't count towards the total */
1026
	return str-buf;
1027
 
1028
}
1029
 
1030
/**
1031
 * snprintf - Format a string and place it in a buffer
1032
 * @buf: The buffer to place the result into
1033
 * @size: The size of the buffer, including the trailing null space
1034
 * @fmt: The format string to use
1035
 * @...: Arguments for the format string
1036
 *
1037
 * The return value is the number of characters which would be
1038
 * generated for the given input, excluding the trailing null,
1039
 * as per ISO C99.  If the return is greater than or equal to
1040
 * @size, the resulting string is truncated.
1041
 *
1042
 * See the vsnprintf() documentation for format string extensions over C99.
1043
 */
1044
int snprintf(char * buf, size_t size, const char *fmt, ...)
1045
{
1046
	va_list args;
1047
	int i;
1048
 
1049
	va_start(args, fmt);
1050
	i=vsnprintf(buf,size,fmt,args);
1051
	va_end(args);
1052
	return i;
1053
}
1054
 
1055
/**
1056
 * scnprintf - Format a string and place it in a buffer
1057
 * @buf: The buffer to place the result into
1058
 * @size: The size of the buffer, including the trailing null space
1059
 * @fmt: The format string to use
1060
 * @...: Arguments for the format string
1061
 *
1062
 * The return value is the number of characters written into @buf not including
1063
 * the trailing '\0'. If @size is <= 0 the function returns 0.
1064
 */
1065
 
1066
int scnprintf(char * buf, size_t size, const char *fmt, ...)
1067
{
1068
	va_list args;
1069
	int i;
1070
 
1071
	va_start(args, fmt);
1072
	i = vsnprintf(buf, size, fmt, args);
1073
	va_end(args);
1074
	return (i >= size) ? (size - 1) : i;
1075
}
1076
 
1077
/**
1078
 * vsprintf - Format a string and place it in a buffer
1079
 * @buf: The buffer to place the result into
1080
 * @fmt: The format string to use
1081
 * @args: Arguments for the format string
1082
 *
1083
 * The function returns the number of characters written
1084
 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
1085
 * buffer overflows.
1086
 *
1087
 * Call this function if you are already dealing with a va_list.
1088
 * You probably want sprintf() instead.
1089
 *
1090
 * See the vsnprintf() documentation for format string extensions over C99.
1091
 */
1092
int vsprintf(char *buf, const char *fmt, va_list args)
1093
{
1094
    return vsnprintf(buf, __INT_MAX__, fmt, args);
1095
}
1096
 
1097
/**
1098
 * sprintf - Format a string and place it in a buffer
1099
 * @buf: The buffer to place the result into
1100
 * @fmt: The format string to use
1101
 * @...: Arguments for the format string
1102
 *
1103
 * The function returns the number of characters written
1104
 * into @buf. Use snprintf() or scnprintf() in order to avoid
1105
 * buffer overflows.
1106
 *
1107
 * See the vsnprintf() documentation for format string extensions over C99.
1108
 */
1109
int sprintf(char * buf, const char *fmt, ...)
1110
{
1111
	va_list args;
1112
	int i;
1113
 
1114
	va_start(args, fmt);
1115
    i=vsnprintf(buf, __INT_MAX__, fmt, args);
1116
	va_end(args);
1117
	return i;
1118
}
1119
 
1120
static inline
1121
void api_putc(char c)
1122
{
1123
    if (c == '\n') api_putc('\r');
1124
 
1125
    __asm__ __volatile__(
1126
    "int $0x40"
1127
    ::"a"(63),"b"(1),"c"(c));
1128
}
1129
 
1130
int API print(const char *fmt,...)
1131
{
1132
    char buf[256];
1133
    va_list args;
1134
    int retval;
1135
    int i;
1136
 
1137
    va_start(args, fmt);
1138
    i = vsnprintf(buf, 256, fmt, args);
1139
    va_end(args);
1140
 
1141
    retval = (i >= 256) ? (256 - 1) : i;
1142
 
1143
    for(i = 0; i< retval; i++)
1144
        api_putc(buf[i]);
1145
 
1146
    return retval;
1147
};
1148
 
1149
 
1150
 
1151
#if 0
1152
/**
1153
 * vsscanf - Unformat a buffer into a list of arguments
1154
 * @buf:	input buffer
1155
 * @fmt:	format of buffer
1156
 * @args:	arguments
1157
 */
1158
int vsscanf(const char * buf, const char * fmt, va_list args)
1159
{
1160
	const char *str = buf;
1161
	char *next;
1162
	char digit;
1163
	int num = 0;
1164
	int qualifier;
1165
	int base;
1166
	int field_width;
1167
	int is_sign = 0;
1168
 
1169
	while(*fmt && *str) {
1170
		/* skip any white space in format */
1171
		/* white space in format matchs any amount of
1172
		 * white space, including none, in the input.
1173
		 */
1174
		if (isspace(*fmt)) {
1175
			while (isspace(*fmt))
1176
				++fmt;
1177
			while (isspace(*str))
1178
				++str;
1179
		}
1180
 
1181
		/* anything that is not a conversion must match exactly */
1182
		if (*fmt != '%' && *fmt) {
1183
			if (*fmt++ != *str++)
1184
				break;
1185
			continue;
1186
		}
1187
 
1188
		if (!*fmt)
1189
			break;
1190
		++fmt;
1191
 
1192
		/* skip this conversion.
1193
		 * advance both strings to next white space
1194
		 */
1195
		if (*fmt == '*') {
1196
			while (!isspace(*fmt) && *fmt)
1197
				fmt++;
1198
			while (!isspace(*str) && *str)
1199
				str++;
1200
			continue;
1201
		}
1202
 
1203
		/* get field width */
1204
		field_width = -1;
1205
		if (isdigit(*fmt))
1206
			field_width = skip_atoi(&fmt);
1207
 
1208
		/* get conversion qualifier */
1209
		qualifier = -1;
1210
		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
1211
		    *fmt == 'Z' || *fmt == 'z') {
1212
			qualifier = *fmt++;
1213
			if (unlikely(qualifier == *fmt)) {
1214
				if (qualifier == 'h') {
1215
					qualifier = 'H';
1216
					fmt++;
1217
				} else if (qualifier == 'l') {
1218
					qualifier = 'L';
1219
					fmt++;
1220
				}
1221
			}
1222
		}
1223
		base = 10;
1224
		is_sign = 0;
1225
 
1226
		if (!*fmt || !*str)
1227
			break;
1228
 
1229
		switch(*fmt++) {
1230
		case 'c':
1231
		{
1232
			char *s = (char *) va_arg(args,char*);
1233
			if (field_width == -1)
1234
				field_width = 1;
1235
			do {
1236
				*s++ = *str++;
1237
			} while (--field_width > 0 && *str);
1238
			num++;
1239
		}
1240
		continue;
1241
		case 's':
1242
		{
1243
			char *s = (char *) va_arg(args, char *);
1244
			if(field_width == -1)
1245
				field_width = INT_MAX;
1246
			/* first, skip leading white space in buffer */
1247
			while (isspace(*str))
1248
				str++;
1249
 
1250
			/* now copy until next white space */
1251
			while (*str && !isspace(*str) && field_width--) {
1252
				*s++ = *str++;
1253
			}
1254
			*s = '\0';
1255
			num++;
1256
		}
1257
		continue;
1258
		case 'n':
1259
			/* return number of characters read so far */
1260
		{
1261
			int *i = (int *)va_arg(args,int*);
1262
			*i = str - buf;
1263
		}
1264
		continue;
1265
		case 'o':
1266
			base = 8;
1267
			break;
1268
		case 'x':
1269
		case 'X':
1270
			base = 16;
1271
			break;
1272
		case 'i':
1273
                        base = 0;
1274
		case 'd':
1275
			is_sign = 1;
1276
		case 'u':
1277
			break;
1278
		case '%':
1279
			/* looking for '%' in str */
1280
			if (*str++ != '%')
1281
				return num;
1282
			continue;
1283
		default:
1284
			/* invalid format; stop here */
1285
			return num;
1286
		}
1287
 
1288
		/* have some sort of integer conversion.
1289
		 * first, skip white space in buffer.
1290
		 */
1291
		while (isspace(*str))
1292
			str++;
1293
 
1294
		digit = *str;
1295
		if (is_sign && digit == '-')
1296
			digit = *(str + 1);
1297
 
1298
		if (!digit
1299
                    || (base == 16 && !isxdigit(digit))
1300
                    || (base == 10 && !isdigit(digit))
1301
                    || (base == 8 && (!isdigit(digit) || digit > '7'))
1302
                    || (base == 0 && !isdigit(digit)))
1303
				break;
1304
 
1305
		switch(qualifier) {
1306
		case 'H':	/* that's 'hh' in format */
1307
			if (is_sign) {
1308
				signed char *s = (signed char *) va_arg(args,signed char *);
1309
				*s = (signed char) simple_strtol(str,&next,base);
1310
			} else {
1311
				unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
1312
				*s = (unsigned char) simple_strtoul(str, &next, base);
1313
			}
1314
			break;
1315
		case 'h':
1316
			if (is_sign) {
1317
				short *s = (short *) va_arg(args,short *);
1318
				*s = (short) simple_strtol(str,&next,base);
1319
			} else {
1320
				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
1321
				*s = (unsigned short) simple_strtoul(str, &next, base);
1322
			}
1323
			break;
1324
		case 'l':
1325
			if (is_sign) {
1326
				long *l = (long *) va_arg(args,long *);
1327
				*l = simple_strtol(str,&next,base);
1328
			} else {
1329
				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
1330
				*l = simple_strtoul(str,&next,base);
1331
			}
1332
			break;
1333
		case 'L':
1334
			if (is_sign) {
1335
				long long *l = (long long*) va_arg(args,long long *);
1336
				*l = simple_strtoll(str,&next,base);
1337
			} else {
1338
				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
1339
				*l = simple_strtoull(str,&next,base);
1340
			}
1341
			break;
1342
		case 'Z':
1343
		case 'z':
1344
		{
1345
			size_t *s = (size_t*) va_arg(args,size_t*);
1346
			*s = (size_t) simple_strtoul(str,&next,base);
1347
		}
1348
		break;
1349
		default:
1350
			if (is_sign) {
1351
				int *i = (int *) va_arg(args, int*);
1352
				*i = (int) simple_strtol(str,&next,base);
1353
			} else {
1354
				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
1355
				*i = (unsigned int) simple_strtoul(str,&next,base);
1356
			}
1357
			break;
1358
		}
1359
		num++;
1360
 
1361
		if (!next)
1362
			break;
1363
		str = next;
1364
	}
1365
 
1366
	/*
1367
	 * Now we've come all the way through so either the input string or the
1368
	 * format ended. In the former case, there can be a %n at the current
1369
	 * position in the format that needs to be filled.
1370
	 */
1371
	if (*fmt == '%' && *(fmt + 1) == 'n') {
1372
		int *p = (int *)va_arg(args, int *);
1373
		*p = str - buf;
1374
	}
1375
 
1376
	return num;
1377
}
1378
#endif
1379