Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: utprint - Formatted printing routines
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, Intel Corp.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include 
45
#include "accommon.h"
46
 
47
#define _COMPONENT          ACPI_UTILITIES
48
ACPI_MODULE_NAME("utprint")
49
 
50
#define ACPI_FORMAT_SIGN            0x01
51
#define ACPI_FORMAT_SIGN_PLUS       0x02
52
#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
53
#define ACPI_FORMAT_ZERO            0x08
54
#define ACPI_FORMAT_LEFT            0x10
55
#define ACPI_FORMAT_UPPER           0x20
56
#define ACPI_FORMAT_PREFIX          0x40
57
/* Local prototypes */
58
static acpi_size
59
acpi_ut_bound_string_length(const char *string, acpi_size count);
60
 
61
static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
62
 
63
static char *acpi_ut_format_number(char *string,
64
				   char *end,
65
				   u64 number,
66
				   u8 base, s32 width, s32 precision, u8 type);
67
 
68
static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
69
 
70
/* Module globals */
71
 
72
static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
73
static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
74
 
75
/*******************************************************************************
76
 *
77
 * FUNCTION:    acpi_ut_bound_string_length
78
 *
79
 * PARAMETERS:  string              - String with boundary
80
 *              count               - Boundary of the string
81
 *
82
 * RETURN:      Length of the string. Less than or equal to Count.
83
 *
84
 * DESCRIPTION: Calculate the length of a string with boundary.
85
 *
86
 ******************************************************************************/
87
 
88
static acpi_size
89
acpi_ut_bound_string_length(const char *string, acpi_size count)
90
{
91
	u32 length = 0;
92
 
93
	while (*string && count) {
94
		length++;
95
		string++;
96
		count--;
97
	}
98
 
99
	return (length);
100
}
101
 
102
/*******************************************************************************
103
 *
104
 * FUNCTION:    acpi_ut_bound_string_output
105
 *
106
 * PARAMETERS:  string              - String with boundary
107
 *              end                 - Boundary of the string
108
 *              c                   - Character to be output to the string
109
 *
110
 * RETURN:      Updated position for next valid character
111
 *
112
 * DESCRIPTION: Output a character into a string with boundary check.
113
 *
114
 ******************************************************************************/
115
 
116
static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
117
{
118
 
119
	if (string < end) {
120
		*string = c;
121
	}
122
 
123
	++string;
124
	return (string);
125
}
126
 
127
/*******************************************************************************
128
 *
129
 * FUNCTION:    acpi_ut_put_number
130
 *
131
 * PARAMETERS:  string              - Buffer to hold reverse-ordered string
132
 *              number              - Integer to be converted
133
 *              base                - Base of the integer
134
 *              upper               - Whether or not using upper cased digits
135
 *
136
 * RETURN:      Updated position for next valid character
137
 *
138
 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
139
 *              reversed ordered number without the trailing zero.
140
 *
141
 ******************************************************************************/
142
 
143
static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
144
{
145
	const char *digits;
146
	u64 digit_index;
147
	char *pos;
148
 
149
	pos = string;
150
	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
151
 
152
	if (number == 0) {
153
		*(pos++) = '0';
154
	} else {
155
		while (number) {
156
			(void)acpi_ut_divide(number, base, &number,
157
					     &digit_index);
158
			*(pos++) = digits[digit_index];
159
		}
160
	}
161
 
162
	/* *(Pos++) = '0'; */
163
	return (pos);
164
}
165
 
166
/*******************************************************************************
167
 *
168
 * FUNCTION:    acpi_ut_scan_number
169
 *
170
 * PARAMETERS:  string              - String buffer
171
 *              number_ptr          - Where the number is returned
172
 *
173
 * RETURN:      Updated position for next valid character
174
 *
175
 * DESCRIPTION: Scan a string for a decimal integer.
176
 *
177
 ******************************************************************************/
178
 
179
const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
180
{
181
	u64 number = 0;
182
 
183
	while (isdigit((int)*string)) {
184
		number *= 10;
185
		number += *(string++) - '0';
186
	}
187
 
188
	*number_ptr = number;
189
	return (string);
190
}
191
 
192
/*******************************************************************************
193
 *
194
 * FUNCTION:    acpi_ut_print_number
195
 *
196
 * PARAMETERS:  string              - String buffer
197
 *              number              - The number to be converted
198
 *
199
 * RETURN:      Updated position for next valid character
200
 *
201
 * DESCRIPTION: Print a decimal integer into a string.
202
 *
203
 ******************************************************************************/
204
 
205
const char *acpi_ut_print_number(char *string, u64 number)
206
{
207
	char ascii_string[20];
208
	const char *pos1;
209
	char *pos2;
210
 
211
	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
212
	pos2 = string;
213
 
214
	while (pos1 != ascii_string) {
215
		*(pos2++) = *(--pos1);
216
	}
217
 
218
	*pos2 = 0;
219
	return (string);
220
}
221
 
222
/*******************************************************************************
223
 *
224
 * FUNCTION:    acpi_ut_format_number
225
 *
226
 * PARAMETERS:  string              - String buffer with boundary
227
 *              end                 - Boundary of the string
228
 *              number              - The number to be converted
229
 *              base                - Base of the integer
230
 *              width               - Field width
231
 *              precision           - Precision of the integer
232
 *              type                - Special printing flags
233
 *
234
 * RETURN:      Updated position for next valid character
235
 *
236
 * DESCRIPTION: Print an integer into a string with any base and any precision.
237
 *
238
 ******************************************************************************/
239
 
240
static char *acpi_ut_format_number(char *string,
241
				   char *end,
242
				   u64 number,
243
				   u8 base, s32 width, s32 precision, u8 type)
244
{
245
	char *pos;
246
	char sign;
247
	char zero;
248
	u8 need_prefix;
249
	u8 upper;
250
	s32 i;
251
	char reversed_string[66];
252
 
253
	/* Parameter validation */
254
 
255
	if (base < 2 || base > 16) {
256
		return (NULL);
257
	}
258
 
259
	if (type & ACPI_FORMAT_LEFT) {
260
		type &= ~ACPI_FORMAT_ZERO;
261
	}
262
 
263
	need_prefix = ((type & ACPI_FORMAT_PREFIX)
264
		       && base != 10) ? TRUE : FALSE;
265
	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
266
	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
267
 
268
	/* Calculate size according to sign and prefix */
269
 
270
	sign = '\0';
271
	if (type & ACPI_FORMAT_SIGN) {
272
		if ((s64) number < 0) {
273
			sign = '-';
274
			number = -(s64) number;
275
			width--;
276
		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
277
			sign = '+';
278
			width--;
279
		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
280
			sign = ' ';
281
			width--;
282
		}
283
	}
284
	if (need_prefix) {
285
		width--;
286
		if (base == 16) {
287
			width--;
288
		}
289
	}
290
 
291
	/* Generate full string in reverse order */
292
 
293
	pos = acpi_ut_put_number(reversed_string, number, base, upper);
294
	i = ACPI_PTR_DIFF(pos, reversed_string);
295
 
296
	/* Printing 100 using %2d gives "100", not "00" */
297
 
298
	if (i > precision) {
299
		precision = i;
300
	}
301
 
302
	width -= precision;
303
 
304
	/* Output the string */
305
 
306
	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
307
		while (--width >= 0) {
308
			string = acpi_ut_bound_string_output(string, end, ' ');
309
		}
310
	}
311
	if (sign) {
312
		string = acpi_ut_bound_string_output(string, end, sign);
313
	}
314
	if (need_prefix) {
315
		string = acpi_ut_bound_string_output(string, end, '0');
316
		if (base == 16) {
317
			string = acpi_ut_bound_string_output(string, end,
318
							     upper ? 'X' : 'x');
319
		}
320
	}
321
	if (!(type & ACPI_FORMAT_LEFT)) {
322
		while (--width >= 0) {
323
			string = acpi_ut_bound_string_output(string, end, zero);
324
		}
325
	}
326
 
327
	while (i <= --precision) {
328
		string = acpi_ut_bound_string_output(string, end, '0');
329
	}
330
	while (--i >= 0) {
331
		string = acpi_ut_bound_string_output(string, end,
332
						     reversed_string[i]);
333
	}
334
	while (--width >= 0) {
335
		string = acpi_ut_bound_string_output(string, end, ' ');
336
	}
337
 
338
	return (string);
339
}
340
 
341
/*******************************************************************************
342
 *
343
 * FUNCTION:    acpi_ut_vsnprintf
344
 *
345
 * PARAMETERS:  string              - String with boundary
346
 *              size                - Boundary of the string
347
 *              format              - Standard printf format
348
 *              args                - Argument list
349
 *
350
 * RETURN:      Number of bytes actually written.
351
 *
352
 * DESCRIPTION: Formatted output to a string using argument list pointer.
353
 *
354
 ******************************************************************************/
355
 
356
int
357
acpi_ut_vsnprintf(char *string,
358
		  acpi_size size, const char *format, va_list args)
359
{
360
	u8 base;
361
	u8 type;
362
	s32 width;
363
	s32 precision;
364
	char qualifier;
365
	u64 number;
366
	char *pos;
367
	char *end;
368
	char c;
369
	const char *s;
370
	const void *p;
371
	s32 length;
372
	int i;
373
 
374
	pos = string;
375
	end = string + size;
376
 
377
	for (; *format; ++format) {
378
		if (*format != '%') {
379
			pos = acpi_ut_bound_string_output(pos, end, *format);
380
			continue;
381
		}
382
 
383
		type = 0;
384
		base = 10;
385
 
386
		/* Process sign */
387
 
388
		do {
389
			++format;
390
			if (*format == '#') {
391
				type |= ACPI_FORMAT_PREFIX;
392
			} else if (*format == '0') {
393
				type |= ACPI_FORMAT_ZERO;
394
			} else if (*format == '+') {
395
				type |= ACPI_FORMAT_SIGN_PLUS;
396
			} else if (*format == ' ') {
397
				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
398
			} else if (*format == '-') {
399
				type |= ACPI_FORMAT_LEFT;
400
			} else {
401
				break;
402
			}
403
		} while (1);
404
 
405
		/* Process width */
406
 
407
		width = -1;
408
		if (isdigit((int)*format)) {
409
			format = acpi_ut_scan_number(format, &number);
410
			width = (s32) number;
411
		} else if (*format == '*') {
412
			++format;
413
			width = va_arg(args, int);
414
			if (width < 0) {
415
				width = -width;
416
				type |= ACPI_FORMAT_LEFT;
417
			}
418
		}
419
 
420
		/* Process precision */
421
 
422
		precision = -1;
423
		if (*format == '.') {
424
			++format;
425
			if (isdigit((int)*format)) {
426
				format = acpi_ut_scan_number(format, &number);
427
				precision = (s32) number;
428
			} else if (*format == '*') {
429
				++format;
430
				precision = va_arg(args, int);
431
			}
432
			if (precision < 0) {
433
				precision = 0;
434
			}
435
		}
436
 
437
		/* Process qualifier */
438
 
439
		qualifier = -1;
440
		if (*format == 'h' || *format == 'l' || *format == 'L') {
441
			qualifier = *format;
442
			++format;
443
 
444
			if (qualifier == 'l' && *format == 'l') {
445
				qualifier = 'L';
446
				++format;
447
			}
448
		}
449
 
450
		switch (*format) {
451
		case '%':
452
 
453
			pos = acpi_ut_bound_string_output(pos, end, '%');
454
			continue;
455
 
456
		case 'c':
457
 
458
			if (!(type & ACPI_FORMAT_LEFT)) {
459
				while (--width > 0) {
460
					pos =
461
					    acpi_ut_bound_string_output(pos,
462
									end,
463
									' ');
464
				}
465
			}
466
 
467
			c = (char)va_arg(args, int);
468
			pos = acpi_ut_bound_string_output(pos, end, c);
469
 
470
			while (--width > 0) {
471
				pos =
472
				    acpi_ut_bound_string_output(pos, end, ' ');
473
			}
474
			continue;
475
 
476
		case 's':
477
 
478
			s = va_arg(args, char *);
479
			if (!s) {
480
				s = "";
481
			}
482
			length = acpi_ut_bound_string_length(s, precision);
483
			if (!(type & ACPI_FORMAT_LEFT)) {
484
				while (length < width--) {
485
					pos =
486
					    acpi_ut_bound_string_output(pos,
487
									end,
488
									' ');
489
				}
490
			}
491
			for (i = 0; i < length; ++i) {
492
				pos = acpi_ut_bound_string_output(pos, end, *s);
493
				++s;
494
			}
495
			while (length < width--) {
496
				pos =
497
				    acpi_ut_bound_string_output(pos, end, ' ');
498
			}
499
			continue;
500
 
501
		case 'o':
502
 
503
			base = 8;
504
			break;
505
 
506
		case 'X':
507
 
508
			type |= ACPI_FORMAT_UPPER;
509
 
510
		case 'x':
511
 
512
			base = 16;
513
			break;
514
 
515
		case 'd':
516
		case 'i':
517
 
518
			type |= ACPI_FORMAT_SIGN;
519
 
520
		case 'u':
521
 
522
			break;
523
 
524
		case 'p':
525
 
526
			if (width == -1) {
527
				width = 2 * sizeof(void *);
528
				type |= ACPI_FORMAT_ZERO;
529
			}
530
 
531
			p = va_arg(args, void *);
532
			pos = acpi_ut_format_number(pos, end,
533
						    ACPI_TO_INTEGER(p), 16,
534
						    width, precision, type);
535
			continue;
536
 
537
		default:
538
 
539
			pos = acpi_ut_bound_string_output(pos, end, '%');
540
			if (*format) {
541
				pos =
542
				    acpi_ut_bound_string_output(pos, end,
543
								*format);
544
			} else {
545
				--format;
546
			}
547
			continue;
548
		}
549
 
550
		if (qualifier == 'L') {
551
			number = va_arg(args, u64);
552
			if (type & ACPI_FORMAT_SIGN) {
553
				number = (s64) number;
554
			}
555
		} else if (qualifier == 'l') {
556
			number = va_arg(args, unsigned long);
557
			if (type & ACPI_FORMAT_SIGN) {
558
				number = (s32) number;
559
			}
560
		} else if (qualifier == 'h') {
561
			number = (u16)va_arg(args, int);
562
			if (type & ACPI_FORMAT_SIGN) {
563
				number = (s16) number;
564
			}
565
		} else {
566
			number = va_arg(args, unsigned int);
567
			if (type & ACPI_FORMAT_SIGN) {
568
				number = (signed int)number;
569
			}
570
		}
571
 
572
		pos = acpi_ut_format_number(pos, end, number, base,
573
					    width, precision, type);
574
	}
575
 
576
	if (size > 0) {
577
		if (pos < end) {
578
			*pos = '\0';
579
		} else {
580
			end[-1] = '\0';
581
		}
582
	}
583
 
584
	return (ACPI_PTR_DIFF(pos, string));
585
}
586
 
587
/*******************************************************************************
588
 *
589
 * FUNCTION:    acpi_ut_snprintf
590
 *
591
 * PARAMETERS:  string              - String with boundary
592
 *              size                - Boundary of the string
593
 *              Format, ...         - Standard printf format
594
 *
595
 * RETURN:      Number of bytes actually written.
596
 *
597
 * DESCRIPTION: Formatted output to a string.
598
 *
599
 ******************************************************************************/
600
 
601
int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
602
{
603
	va_list args;
604
	int length;
605
 
606
	va_start(args, format);
607
	length = acpi_ut_vsnprintf(string, size, format, args);
608
	va_end(args);
609
 
610
	return (length);
611
}
612
 
613
#ifdef ACPI_APPLICATION
614
/*******************************************************************************
615
 *
616
 * FUNCTION:    acpi_ut_file_vprintf
617
 *
618
 * PARAMETERS:  file                - File descriptor
619
 *              format              - Standard printf format
620
 *              args                - Argument list
621
 *
622
 * RETURN:      Number of bytes actually written.
623
 *
624
 * DESCRIPTION: Formatted output to a file using argument list pointer.
625
 *
626
 ******************************************************************************/
627
 
628
int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
629
{
630
	acpi_cpu_flags flags;
631
	int length;
632
 
633
	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
634
	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
635
				   sizeof(acpi_gbl_print_buffer), format, args);
636
 
637
	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
638
	acpi_os_release_lock(acpi_gbl_print_lock, flags);
639
 
640
	return (length);
641
}
642
 
643
/*******************************************************************************
644
 *
645
 * FUNCTION:    acpi_ut_file_printf
646
 *
647
 * PARAMETERS:  file                - File descriptor
648
 *              Format, ...         - Standard printf format
649
 *
650
 * RETURN:      Number of bytes actually written.
651
 *
652
 * DESCRIPTION: Formatted output to a file.
653
 *
654
 ******************************************************************************/
655
 
656
int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
657
{
658
	va_list args;
659
	int length;
660
 
661
	va_start(args, format);
662
	length = acpi_ut_file_vprintf(file, format, args);
663
	va_end(args);
664
 
665
	return (length);
666
}
667
#endif