GNU Linux-libre 4.19.211-gnu1
[releases.git] / drivers / acpi / acpica / utprint.c
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 - 2018, 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
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
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
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
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
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
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
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         end = string + size;
336
337         for (; *format; ++format) {
338                 if (*format != '%') {
339                         pos = acpi_ut_bound_string_output(pos, end, *format);
340                         continue;
341                 }
342
343                 type = 0;
344                 base = 10;
345
346                 /* Process sign */
347
348                 do {
349                         ++format;
350                         if (*format == '#') {
351                                 type |= ACPI_FORMAT_PREFIX;
352                         } else if (*format == '0') {
353                                 type |= ACPI_FORMAT_ZERO;
354                         } else if (*format == '+') {
355                                 type |= ACPI_FORMAT_SIGN_PLUS;
356                         } else if (*format == ' ') {
357                                 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
358                         } else if (*format == '-') {
359                                 type |= ACPI_FORMAT_LEFT;
360                         } else {
361                                 break;
362                         }
363
364                 } while (1);
365
366                 /* Process width */
367
368                 width = -1;
369                 if (isdigit((int)*format)) {
370                         format = acpi_ut_scan_number(format, &number);
371                         width = (s32)number;
372                 } else if (*format == '*') {
373                         ++format;
374                         width = va_arg(args, int);
375                         if (width < 0) {
376                                 width = -width;
377                                 type |= ACPI_FORMAT_LEFT;
378                         }
379                 }
380
381                 /* Process precision */
382
383                 precision = -1;
384                 if (*format == '.') {
385                         ++format;
386                         if (isdigit((int)*format)) {
387                                 format = acpi_ut_scan_number(format, &number);
388                                 precision = (s32)number;
389                         } else if (*format == '*') {
390                                 ++format;
391                                 precision = va_arg(args, int);
392                         }
393
394                         if (precision < 0) {
395                                 precision = 0;
396                         }
397                 }
398
399                 /* Process qualifier */
400
401                 qualifier = -1;
402                 if (*format == 'h' || *format == 'l' || *format == 'L') {
403                         qualifier = *format;
404                         ++format;
405
406                         if (qualifier == 'l' && *format == 'l') {
407                                 qualifier = 'L';
408                                 ++format;
409                         }
410                 }
411
412                 switch (*format) {
413                 case '%':
414
415                         pos = acpi_ut_bound_string_output(pos, end, '%');
416                         continue;
417
418                 case 'c':
419
420                         if (!(type & ACPI_FORMAT_LEFT)) {
421                                 while (--width > 0) {
422                                         pos =
423                                             acpi_ut_bound_string_output(pos,
424                                                                         end,
425                                                                         ' ');
426                                 }
427                         }
428
429                         c = (char)va_arg(args, int);
430                         pos = acpi_ut_bound_string_output(pos, end, c);
431
432                         while (--width > 0) {
433                                 pos =
434                                     acpi_ut_bound_string_output(pos, end, ' ');
435                         }
436                         continue;
437
438                 case 's':
439
440                         s = va_arg(args, char *);
441                         if (!s) {
442                                 s = "<NULL>";
443                         }
444                         length = (s32)acpi_ut_bound_string_length(s, precision);
445                         if (!(type & ACPI_FORMAT_LEFT)) {
446                                 while (length < width--) {
447                                         pos =
448                                             acpi_ut_bound_string_output(pos,
449                                                                         end,
450                                                                         ' ');
451                                 }
452                         }
453
454                         for (i = 0; i < length; ++i) {
455                                 pos = acpi_ut_bound_string_output(pos, end, *s);
456                                 ++s;
457                         }
458
459                         while (length < width--) {
460                                 pos =
461                                     acpi_ut_bound_string_output(pos, end, ' ');
462                         }
463                         continue;
464
465                 case 'o':
466
467                         base = 8;
468                         break;
469
470                 case 'X':
471
472                         type |= ACPI_FORMAT_UPPER;
473                         /* FALLTHROUGH */
474
475                 case 'x':
476
477                         base = 16;
478                         break;
479
480                 case 'd':
481                 case 'i':
482
483                         type |= ACPI_FORMAT_SIGN;
484
485                 case 'u':
486
487                         break;
488
489                 case 'p':
490
491                         if (width == -1) {
492                                 width = 2 * sizeof(void *);
493                                 type |= ACPI_FORMAT_ZERO;
494                         }
495
496                         p = va_arg(args, void *);
497                         pos =
498                             acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
499                                                   16, width, precision, type);
500                         continue;
501
502                 default:
503
504                         pos = acpi_ut_bound_string_output(pos, end, '%');
505                         if (*format) {
506                                 pos =
507                                     acpi_ut_bound_string_output(pos, end,
508                                                                 *format);
509                         } else {
510                                 --format;
511                         }
512                         continue;
513                 }
514
515                 if (qualifier == 'L') {
516                         number = va_arg(args, u64);
517                         if (type & ACPI_FORMAT_SIGN) {
518                                 number = (s64)number;
519                         }
520                 } else if (qualifier == 'l') {
521                         number = va_arg(args, unsigned long);
522                         if (type & ACPI_FORMAT_SIGN) {
523                                 number = (s32)number;
524                         }
525                 } else if (qualifier == 'h') {
526                         number = (u16)va_arg(args, int);
527                         if (type & ACPI_FORMAT_SIGN) {
528                                 number = (s16)number;
529                         }
530                 } else {
531                         number = va_arg(args, unsigned int);
532                         if (type & ACPI_FORMAT_SIGN) {
533                                 number = (signed int)number;
534                         }
535                 }
536
537                 pos = acpi_ut_format_number(pos, end, number, base,
538                                             width, precision, type);
539         }
540
541         if (size > 0) {
542                 if (pos < end) {
543                         *pos = '\0';
544                 } else {
545                         end[-1] = '\0';
546                 }
547         }
548
549         return ((int)ACPI_PTR_DIFF(pos, string));
550 }
551
552 /*******************************************************************************
553  *
554  * FUNCTION:    snprintf
555  *
556  * PARAMETERS:  string              - String with boundary
557  *              size                - Boundary of the string
558  *              Format, ...         - Standard printf format
559  *
560  * RETURN:      Number of bytes actually written.
561  *
562  * DESCRIPTION: Formatted output to a string.
563  *
564  ******************************************************************************/
565
566 int snprintf(char *string, acpi_size size, const char *format, ...)
567 {
568         va_list args;
569         int length;
570
571         va_start(args, format);
572         length = vsnprintf(string, size, format, args);
573         va_end(args);
574
575         return (length);
576 }
577
578 /*******************************************************************************
579  *
580  * FUNCTION:    sprintf
581  *
582  * PARAMETERS:  string              - String with boundary
583  *              Format, ...         - Standard printf format
584  *
585  * RETURN:      Number of bytes actually written.
586  *
587  * DESCRIPTION: Formatted output to a string.
588  *
589  ******************************************************************************/
590
591 int sprintf(char *string, const char *format, ...)
592 {
593         va_list args;
594         int length;
595
596         va_start(args, format);
597         length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
598         va_end(args);
599
600         return (length);
601 }
602
603 #ifdef ACPI_APPLICATION
604 /*******************************************************************************
605  *
606  * FUNCTION:    vprintf
607  *
608  * PARAMETERS:  format              - Standard printf format
609  *              args                - Argument list
610  *
611  * RETURN:      Number of bytes actually written.
612  *
613  * DESCRIPTION: Formatted output to stdout using argument list pointer.
614  *
615  ******************************************************************************/
616
617 int vprintf(const char *format, va_list args)
618 {
619         acpi_cpu_flags flags;
620         int length;
621
622         flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
623         length = vsnprintf(acpi_gbl_print_buffer,
624                            sizeof(acpi_gbl_print_buffer), format, args);
625
626         (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
627         acpi_os_release_lock(acpi_gbl_print_lock, flags);
628
629         return (length);
630 }
631
632 /*******************************************************************************
633  *
634  * FUNCTION:    printf
635  *
636  * PARAMETERS:  Format, ...         - Standard printf format
637  *
638  * RETURN:      Number of bytes actually written.
639  *
640  * DESCRIPTION: Formatted output to stdout.
641  *
642  ******************************************************************************/
643
644 int printf(const char *format, ...)
645 {
646         va_list args;
647         int length;
648
649         va_start(args, format);
650         length = vprintf(format, args);
651         va_end(args);
652
653         return (length);
654 }
655
656 /*******************************************************************************
657  *
658  * FUNCTION:    vfprintf
659  *
660  * PARAMETERS:  file                - File descriptor
661  *              format              - Standard printf format
662  *              args                - Argument list
663  *
664  * RETURN:      Number of bytes actually written.
665  *
666  * DESCRIPTION: Formatted output to a file using argument list pointer.
667  *
668  ******************************************************************************/
669
670 int vfprintf(FILE * file, const char *format, va_list args)
671 {
672         acpi_cpu_flags flags;
673         int length;
674
675         flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
676         length = vsnprintf(acpi_gbl_print_buffer,
677                            sizeof(acpi_gbl_print_buffer), format, args);
678
679         (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
680         acpi_os_release_lock(acpi_gbl_print_lock, flags);
681
682         return (length);
683 }
684
685 /*******************************************************************************
686  *
687  * FUNCTION:    fprintf
688  *
689  * PARAMETERS:  file                - File descriptor
690  *              Format, ...         - Standard printf format
691  *
692  * RETURN:      Number of bytes actually written.
693  *
694  * DESCRIPTION: Formatted output to a file.
695  *
696  ******************************************************************************/
697
698 int fprintf(FILE * file, const char *format, ...)
699 {
700         va_list args;
701         int length;
702
703         va_start(args, format);
704         length = vfprintf(file, format, args);
705         va_end(args);
706
707         return (length);
708 }
709 #endif