1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46
47#define _COMPONENT ACPI_UTILITIES
48ACPI_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
58static acpi_size
59acpi_ut_bound_string_length(const char *string, acpi_size count);
60
61static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
62
63static char *acpi_ut_format_number(char *string,
64 char *end,
65 u64 number,
66 u8 base, s32 width, s32 precision, u8 type);
67
68static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
69
70
71
72static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
73static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88static acpi_size
89acpi_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
105
106
107
108
109
110
111
112
113
114
115
116static 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143static 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
163 return (pos);
164}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179const 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
195
196
197
198
199
200
201
202
203
204
205const 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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240static 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 sign;
246 char zero;
247 u8 need_prefix;
248 u8 upper;
249 s32 i;
250 char reversed_string[66];
251
252
253
254 if (base < 2 || base > 16) {
255 return (NULL);
256 }
257
258 if (type & ACPI_FORMAT_LEFT) {
259 type &= ~ACPI_FORMAT_ZERO;
260 }
261
262 need_prefix = ((type & ACPI_FORMAT_PREFIX)
263 && base != 10) ? TRUE : FALSE;
264 upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
265 zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
266
267
268
269 sign = '\0';
270 if (type & ACPI_FORMAT_SIGN) {
271 if ((s64) number < 0) {
272 sign = '-';
273 number = -(s64) number;
274 width--;
275 } else if (type & ACPI_FORMAT_SIGN_PLUS) {
276 sign = '+';
277 width--;
278 } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
279 sign = ' ';
280 width--;
281 }
282 }
283 if (need_prefix) {
284 width--;
285 if (base == 16) {
286 width--;
287 }
288 }
289
290
291
292 i = ACPI_PTR_DIFF(acpi_ut_put_number
293 (reversed_string, number, base, upper),
294 reversed_string);
295
296
297
298 if (i > precision) {
299 precision = i;
300 }
301
302 width -= precision;
303
304
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
344
345
346
347
348
349
350
351
352
353
354
355
356int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
357{
358 u8 base = 10;
359 u8 type = 0;
360 s32 width = -1;
361 s32 precision = -1;
362 char qualifier = 0;
363 u64 number;
364 char *pos;
365 char *end;
366 char c;
367 const char *s;
368 const void *p;
369 s32 length;
370 int i;
371
372 pos = string;
373 end = string + size;
374
375 for (; *format; ++format) {
376 if (*format != '%') {
377 pos = acpi_ut_bound_string_output(pos, end, *format);
378 continue;
379 }
380
381
382
383 do {
384 ++format;
385 if (*format == '#') {
386 type |= ACPI_FORMAT_PREFIX;
387 } else if (*format == '0') {
388 type |= ACPI_FORMAT_ZERO;
389 } else if (*format == '+') {
390 type |= ACPI_FORMAT_SIGN_PLUS;
391 } else if (*format == ' ') {
392 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
393 } else if (*format == '-') {
394 type |= ACPI_FORMAT_LEFT;
395 } else {
396 break;
397 }
398 } while (1);
399
400
401
402 width = -1;
403 if (isdigit((int)*format)) {
404 format = acpi_ut_scan_number(format, &number);
405 width = (s32) number;
406 } else if (*format == '*') {
407 ++format;
408 width = va_arg(args, int);
409 if (width < 0) {
410 width = -width;
411 type |= ACPI_FORMAT_LEFT;
412 }
413 }
414
415
416
417 precision = -1;
418 if (*format == '.') {
419 ++format;
420 if (isdigit((int)*format)) {
421 format = acpi_ut_scan_number(format, &number);
422 precision = (s32) number;
423 } else if (*format == '*') {
424 ++format;
425 precision = va_arg(args, int);
426 }
427 if (precision < 0) {
428 precision = 0;
429 }
430 }
431
432
433
434 qualifier = -1;
435 if (*format == 'h' || *format == 'l' || *format == 'L') {
436 qualifier = *format;
437 ++format;
438
439 if (qualifier == 'l' && *format == 'l') {
440 qualifier = 'L';
441 ++format;
442 }
443 }
444
445 switch (*format) {
446 case '%':
447
448 pos = acpi_ut_bound_string_output(pos, end, '%');
449 continue;
450
451 case 'c':
452
453 if (!(type & ACPI_FORMAT_LEFT)) {
454 while (--width > 0) {
455 pos =
456 acpi_ut_bound_string_output(pos,
457 end,
458 ' ');
459 }
460 }
461
462 c = (char)va_arg(args, int);
463 pos = acpi_ut_bound_string_output(pos, end, c);
464
465 while (--width > 0) {
466 pos =
467 acpi_ut_bound_string_output(pos, end, ' ');
468 }
469 continue;
470
471 case 's':
472
473 s = va_arg(args, char *);
474 if (!s) {
475 s = "<NULL>";
476 }
477 length = acpi_ut_bound_string_length(s, precision);
478 if (!(type & ACPI_FORMAT_LEFT)) {
479 while (length < width--) {
480 pos =
481 acpi_ut_bound_string_output(pos,
482 end,
483 ' ');
484 }
485 }
486 for (i = 0; i < length; ++i) {
487 pos = acpi_ut_bound_string_output(pos, end, *s);
488 ++s;
489 }
490 while (length < width--) {
491 pos =
492 acpi_ut_bound_string_output(pos, end, ' ');
493 }
494 continue;
495
496 case 'o':
497
498 base = 8;
499 break;
500
501 case 'X':
502
503 type |= ACPI_FORMAT_UPPER;
504
505 case 'x':
506
507 base = 16;
508 break;
509
510 case 'd':
511 case 'i':
512
513 type |= ACPI_FORMAT_SIGN;
514
515 case 'u':
516
517 break;
518
519 case 'p':
520
521 if (width == -1) {
522 width = 2 * sizeof(void *);
523 type |= ACPI_FORMAT_ZERO;
524 }
525
526 p = va_arg(args, void *);
527 pos = acpi_ut_format_number(pos, end,
528 ACPI_TO_INTEGER(p), 16,
529 width, precision, type);
530 continue;
531
532 default:
533
534 pos = acpi_ut_bound_string_output(pos, end, '%');
535 if (*format) {
536 pos =
537 acpi_ut_bound_string_output(pos, end,
538 *format);
539 } else {
540 --format;
541 }
542 continue;
543 }
544
545 if (qualifier == 'L') {
546 number = va_arg(args, u64);
547 if (type & ACPI_FORMAT_SIGN) {
548 number = (s64) number;
549 }
550 } else if (qualifier == 'l') {
551 number = va_arg(args, unsigned long);
552 if (type & ACPI_FORMAT_SIGN) {
553 number = (s32) number;
554 }
555 } else if (qualifier == 'h') {
556 number = (u16)va_arg(args, int);
557 if (type & ACPI_FORMAT_SIGN) {
558 number = (s16) number;
559 }
560 } else {
561 number = va_arg(args, unsigned int);
562 if (type & ACPI_FORMAT_SIGN) {
563 number = (signed int)number;
564 }
565 }
566
567 pos = acpi_ut_format_number(pos, end, number, base,
568 width, precision, type);
569 }
570
571 if (size > 0) {
572 if (pos < end) {
573 *pos = '\0';
574 } else {
575 end[-1] = '\0';
576 }
577 }
578
579 return (ACPI_PTR_DIFF(pos, string));
580}
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596int snprintf(char *string, acpi_size size, const char *format, ...)
597{
598 va_list args;
599 int length;
600
601 va_start(args, format);
602 length = vsnprintf(string, size, format, args);
603 va_end(args);
604
605 return (length);
606}
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621int sprintf(char *string, const char *format, ...)
622{
623 va_list args;
624 int length;
625
626 va_start(args, format);
627 length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
628 va_end(args);
629
630 return (length);
631}
632
633#ifdef ACPI_APPLICATION
634
635
636
637
638
639
640
641
642
643
644
645
646
647int vprintf(const char *format, va_list args)
648{
649 acpi_cpu_flags flags;
650 int length;
651
652 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
653 length = vsnprintf(acpi_gbl_print_buffer,
654 sizeof(acpi_gbl_print_buffer), format, args);
655
656 (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
657 acpi_os_release_lock(acpi_gbl_print_lock, flags);
658
659 return (length);
660}
661
662
663
664
665
666
667
668
669
670
671
672
673
674int printf(const char *format, ...)
675{
676 va_list args;
677 int length;
678
679 va_start(args, format);
680 length = vprintf(format, args);
681 va_end(args);
682
683 return (length);
684}
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700int vfprintf(FILE * file, const char *format, va_list args)
701{
702 acpi_cpu_flags flags;
703 int length;
704
705 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
706 length = vsnprintf(acpi_gbl_print_buffer,
707 sizeof(acpi_gbl_print_buffer), format, args);
708
709 (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
710 acpi_os_release_lock(acpi_gbl_print_lock, flags);
711
712 return (length);
713}
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728int fprintf(FILE * file, const char *format, ...)
729{
730 va_list args;
731 int length;
732
733 va_start(args, format);
734 length = vfprintf(file, format, args);
735 va_end(args);
736
737 return (length);
738}
739#endif
740