0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012
0013 #define _COMPONENT ACPI_UTILITIES
0014 ACPI_MODULE_NAME("utprint")
0015
0016 #define ACPI_FORMAT_SIGN 0x01
0017 #define ACPI_FORMAT_SIGN_PLUS 0x02
0018 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
0019 #define ACPI_FORMAT_ZERO 0x08
0020 #define ACPI_FORMAT_LEFT 0x10
0021 #define ACPI_FORMAT_UPPER 0x20
0022 #define ACPI_FORMAT_PREFIX 0x40
0023
0024 static acpi_size
0025 acpi_ut_bound_string_length(const char *string, acpi_size count);
0026
0027 static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
0028
0029 static char *acpi_ut_format_number(char *string,
0030 char *end,
0031 u64 number,
0032 u8 base, s32 width, s32 precision, u8 type);
0033
0034 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 static acpi_size
0050 acpi_ut_bound_string_length(const char *string, acpi_size count)
0051 {
0052 u32 length = 0;
0053
0054 while (*string && count) {
0055 length++;
0056 string++;
0057 count--;
0058 }
0059
0060 return (length);
0061 }
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
0078 {
0079
0080 if (string < end) {
0081 *string = c;
0082 }
0083
0084 ++string;
0085 return (string);
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
0105 {
0106 const char *digits;
0107 u64 digit_index;
0108 char *pos;
0109
0110 pos = string;
0111 digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
0112
0113 if (number == 0) {
0114 *(pos++) = '0';
0115 } else {
0116 while (number) {
0117 (void)acpi_ut_divide(number, base, &number,
0118 &digit_index);
0119 *(pos++) = digits[digit_index];
0120 }
0121 }
0122
0123
0124 return (pos);
0125 }
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
0141 {
0142 u64 number = 0;
0143
0144 while (isdigit((int)*string)) {
0145 acpi_ut_short_multiply(number, 10, &number);
0146 number += *(string++) - '0';
0147 }
0148
0149 *number_ptr = number;
0150 return (string);
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 const char *acpi_ut_print_number(char *string, u64 number)
0167 {
0168 char ascii_string[20];
0169 const char *pos1;
0170 char *pos2;
0171
0172 pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
0173 pos2 = string;
0174
0175 while (pos1 != ascii_string) {
0176 *(pos2++) = *(--pos1);
0177 }
0178
0179 *pos2 = 0;
0180 return (string);
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 static char *acpi_ut_format_number(char *string,
0202 char *end,
0203 u64 number,
0204 u8 base, s32 width, s32 precision, u8 type)
0205 {
0206 char *pos;
0207 char sign;
0208 char zero;
0209 u8 need_prefix;
0210 u8 upper;
0211 s32 i;
0212 char reversed_string[66];
0213
0214
0215
0216 if (base < 2 || base > 16) {
0217 return (NULL);
0218 }
0219
0220 if (type & ACPI_FORMAT_LEFT) {
0221 type &= ~ACPI_FORMAT_ZERO;
0222 }
0223
0224 need_prefix = ((type & ACPI_FORMAT_PREFIX)
0225 && base != 10) ? TRUE : FALSE;
0226 upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
0227 zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
0228
0229
0230
0231 sign = '\0';
0232 if (type & ACPI_FORMAT_SIGN) {
0233 if ((s64)number < 0) {
0234 sign = '-';
0235 number = -(s64)number;
0236 width--;
0237 } else if (type & ACPI_FORMAT_SIGN_PLUS) {
0238 sign = '+';
0239 width--;
0240 } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
0241 sign = ' ';
0242 width--;
0243 }
0244 }
0245 if (need_prefix) {
0246 width--;
0247 if (base == 16) {
0248 width--;
0249 }
0250 }
0251
0252
0253
0254 pos = acpi_ut_put_number(reversed_string, number, base, upper);
0255 i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
0256
0257
0258
0259 if (i > precision) {
0260 precision = i;
0261 }
0262
0263 width -= precision;
0264
0265
0266
0267 if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
0268 while (--width >= 0) {
0269 string = acpi_ut_bound_string_output(string, end, ' ');
0270 }
0271 }
0272 if (sign) {
0273 string = acpi_ut_bound_string_output(string, end, sign);
0274 }
0275 if (need_prefix) {
0276 string = acpi_ut_bound_string_output(string, end, '0');
0277 if (base == 16) {
0278 string =
0279 acpi_ut_bound_string_output(string, end,
0280 upper ? 'X' : 'x');
0281 }
0282 }
0283 if (!(type & ACPI_FORMAT_LEFT)) {
0284 while (--width >= 0) {
0285 string = acpi_ut_bound_string_output(string, end, zero);
0286 }
0287 }
0288
0289 while (i <= --precision) {
0290 string = acpi_ut_bound_string_output(string, end, '0');
0291 }
0292 while (--i >= 0) {
0293 string = acpi_ut_bound_string_output(string, end,
0294 reversed_string[i]);
0295 }
0296 while (--width >= 0) {
0297 string = acpi_ut_bound_string_output(string, end, ' ');
0298 }
0299
0300 return (string);
0301 }
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
0319 {
0320 u8 base;
0321 u8 type;
0322 s32 width;
0323 s32 precision;
0324 char qualifier;
0325 u64 number;
0326 char *pos;
0327 char *end;
0328 char c;
0329 const char *s;
0330 const void *p;
0331 s32 length;
0332 int i;
0333
0334 pos = string;
0335
0336 if (size != ACPI_UINT32_MAX) {
0337 end = string + size;
0338 } else {
0339 end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
0340 }
0341
0342 for (; *format; ++format) {
0343 if (*format != '%') {
0344 pos = acpi_ut_bound_string_output(pos, end, *format);
0345 continue;
0346 }
0347
0348 type = 0;
0349 base = 10;
0350
0351
0352
0353 do {
0354 ++format;
0355 if (*format == '#') {
0356 type |= ACPI_FORMAT_PREFIX;
0357 } else if (*format == '0') {
0358 type |= ACPI_FORMAT_ZERO;
0359 } else if (*format == '+') {
0360 type |= ACPI_FORMAT_SIGN_PLUS;
0361 } else if (*format == ' ') {
0362 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
0363 } else if (*format == '-') {
0364 type |= ACPI_FORMAT_LEFT;
0365 } else {
0366 break;
0367 }
0368
0369 } while (1);
0370
0371
0372
0373 width = -1;
0374 if (isdigit((int)*format)) {
0375 format = acpi_ut_scan_number(format, &number);
0376 width = (s32)number;
0377 } else if (*format == '*') {
0378 ++format;
0379 width = va_arg(args, int);
0380 if (width < 0) {
0381 width = -width;
0382 type |= ACPI_FORMAT_LEFT;
0383 }
0384 }
0385
0386
0387
0388 precision = -1;
0389 if (*format == '.') {
0390 ++format;
0391 if (isdigit((int)*format)) {
0392 format = acpi_ut_scan_number(format, &number);
0393 precision = (s32)number;
0394 } else if (*format == '*') {
0395 ++format;
0396 precision = va_arg(args, int);
0397 }
0398
0399 if (precision < 0) {
0400 precision = 0;
0401 }
0402 }
0403
0404
0405
0406 qualifier = -1;
0407 if (*format == 'h' || *format == 'l' || *format == 'L') {
0408 qualifier = *format;
0409 ++format;
0410
0411 if (qualifier == 'l' && *format == 'l') {
0412 qualifier = 'L';
0413 ++format;
0414 }
0415 }
0416
0417 switch (*format) {
0418 case '%':
0419
0420 pos = acpi_ut_bound_string_output(pos, end, '%');
0421 continue;
0422
0423 case 'c':
0424
0425 if (!(type & ACPI_FORMAT_LEFT)) {
0426 while (--width > 0) {
0427 pos =
0428 acpi_ut_bound_string_output(pos,
0429 end,
0430 ' ');
0431 }
0432 }
0433
0434 c = (char)va_arg(args, int);
0435 pos = acpi_ut_bound_string_output(pos, end, c);
0436
0437 while (--width > 0) {
0438 pos =
0439 acpi_ut_bound_string_output(pos, end, ' ');
0440 }
0441 continue;
0442
0443 case 's':
0444
0445 s = va_arg(args, char *);
0446 if (!s) {
0447 s = "<NULL>";
0448 }
0449 length = (s32)acpi_ut_bound_string_length(s, precision);
0450 if (!(type & ACPI_FORMAT_LEFT)) {
0451 while (length < width--) {
0452 pos =
0453 acpi_ut_bound_string_output(pos,
0454 end,
0455 ' ');
0456 }
0457 }
0458
0459 for (i = 0; i < length; ++i) {
0460 pos = acpi_ut_bound_string_output(pos, end, *s);
0461 ++s;
0462 }
0463
0464 while (length < width--) {
0465 pos =
0466 acpi_ut_bound_string_output(pos, end, ' ');
0467 }
0468 continue;
0469
0470 case 'o':
0471
0472 base = 8;
0473 break;
0474
0475 case 'X':
0476
0477 type |= ACPI_FORMAT_UPPER;
0478 ACPI_FALLTHROUGH;
0479
0480 case 'x':
0481
0482 base = 16;
0483 break;
0484
0485 case 'd':
0486 case 'i':
0487
0488 type |= ACPI_FORMAT_SIGN;
0489
0490 case 'u':
0491
0492 break;
0493
0494 case 'p':
0495
0496 if (width == -1) {
0497 width = 2 * sizeof(void *);
0498 type |= ACPI_FORMAT_ZERO;
0499 }
0500
0501 p = va_arg(args, void *);
0502 pos =
0503 acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
0504 16, width, precision, type);
0505 continue;
0506
0507 default:
0508
0509 pos = acpi_ut_bound_string_output(pos, end, '%');
0510 if (*format) {
0511 pos =
0512 acpi_ut_bound_string_output(pos, end,
0513 *format);
0514 } else {
0515 --format;
0516 }
0517 continue;
0518 }
0519
0520 if (qualifier == 'L') {
0521 number = va_arg(args, u64);
0522 if (type & ACPI_FORMAT_SIGN) {
0523 number = (s64)number;
0524 }
0525 } else if (qualifier == 'l') {
0526 number = va_arg(args, unsigned long);
0527 if (type & ACPI_FORMAT_SIGN) {
0528 number = (s32)number;
0529 }
0530 } else if (qualifier == 'h') {
0531 number = (u16)va_arg(args, int);
0532 if (type & ACPI_FORMAT_SIGN) {
0533 number = (s16)number;
0534 }
0535 } else {
0536 number = va_arg(args, unsigned int);
0537 if (type & ACPI_FORMAT_SIGN) {
0538 number = (signed int)number;
0539 }
0540 }
0541
0542 pos = acpi_ut_format_number(pos, end, number, base,
0543 width, precision, type);
0544 }
0545
0546 if (size > 0) {
0547 if (pos < end) {
0548 *pos = '\0';
0549 } else {
0550 end[-1] = '\0';
0551 }
0552 }
0553
0554 return ((int)ACPI_PTR_DIFF(pos, string));
0555 }
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571 int snprintf(char *string, acpi_size size, const char *format, ...)
0572 {
0573 va_list args;
0574 int length;
0575
0576 va_start(args, format);
0577 length = vsnprintf(string, size, format, args);
0578 va_end(args);
0579
0580 return (length);
0581 }
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596 int sprintf(char *string, const char *format, ...)
0597 {
0598 va_list args;
0599 int length;
0600
0601 va_start(args, format);
0602 length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
0603 va_end(args);
0604
0605 return (length);
0606 }
0607
0608 #ifdef ACPI_APPLICATION
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622 int vprintf(const char *format, va_list args)
0623 {
0624 acpi_cpu_flags flags;
0625 int length;
0626
0627 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
0628 length = vsnprintf(acpi_gbl_print_buffer,
0629 sizeof(acpi_gbl_print_buffer), format, args);
0630
0631 (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
0632 acpi_os_release_lock(acpi_gbl_print_lock, flags);
0633
0634 return (length);
0635 }
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649 int printf(const char *format, ...)
0650 {
0651 va_list args;
0652 int length;
0653
0654 va_start(args, format);
0655 length = vprintf(format, args);
0656 va_end(args);
0657
0658 return (length);
0659 }
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675 int vfprintf(FILE * file, const char *format, va_list args)
0676 {
0677 acpi_cpu_flags flags;
0678 int length;
0679
0680 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
0681 length = vsnprintf(acpi_gbl_print_buffer,
0682 sizeof(acpi_gbl_print_buffer), format, args);
0683
0684 (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
0685 acpi_os_release_lock(acpi_gbl_print_lock, flags);
0686
0687 return (length);
0688 }
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703 int fprintf(FILE * file, const char *format, ...)
0704 {
0705 va_list args;
0706 int length;
0707
0708 va_start(args, format);
0709 length = vfprintf(file, format, args);
0710 va_end(args);
0711
0712 return (length);
0713 }
0714 #endif