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