Subversion Repositories Kolibri OS

Rev

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

  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 <acpi/acpi.h>
  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 = "<NULL>";
  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
  668.