Home | History | Annotate | Line # | Download | only in utilities
utstrsuppt.c revision 1.1.1.4
      1 /*******************************************************************************
      2  *
      3  * Module Name: utstrsuppt - Support functions for string-to-integer conversion
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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.h"
     45 #include "accommon.h"
     46 
     47 #define _COMPONENT          ACPI_UTILITIES
     48         ACPI_MODULE_NAME    ("utstrsuppt")
     49 
     50 
     51 /* Local prototypes */
     52 
     53 static ACPI_STATUS
     54 AcpiUtInsertDigit (
     55     UINT64                  *AccumulatedValue,
     56     UINT32                  Base,
     57     int                     AsciiDigit);
     58 
     59 static ACPI_STATUS
     60 AcpiUtStrtoulMultiply64 (
     61     UINT64                  Multiplicand,
     62     UINT32                  Base,
     63     UINT64                  *OutProduct);
     64 
     65 static ACPI_STATUS
     66 AcpiUtStrtoulAdd64 (
     67     UINT64                  Addend1,
     68     UINT32                  Digit,
     69     UINT64                  *OutSum);
     70 
     71 
     72 /*******************************************************************************
     73  *
     74  * FUNCTION:    AcpiUtConvertOctalString
     75  *
     76  * PARAMETERS:  String                  - Null terminated input string
     77  *              ReturnValuePtr          - Where the converted value is returned
     78  *
     79  * RETURN:      Status and 64-bit converted integer
     80  *
     81  * DESCRIPTION: Performs a base 8 conversion of the input string to an
     82  *              integer value, either 32 or 64 bits.
     83  *
     84  * NOTE:        Maximum 64-bit unsigned octal value is 01777777777777777777777
     85  *              Maximum 32-bit unsigned octal value is 037777777777
     86  *
     87  ******************************************************************************/
     88 
     89 ACPI_STATUS
     90 AcpiUtConvertOctalString (
     91     char                    *String,
     92     UINT64                  *ReturnValuePtr)
     93 {
     94     UINT64                  AccumulatedValue = 0;
     95     ACPI_STATUS             Status = AE_OK;
     96 
     97 
     98     /* Convert each ASCII byte in the input string */
     99 
    100     while (*String)
    101     {
    102         /* Character must be ASCII 0-7, otherwise terminate with no error */
    103 
    104         if (!(ACPI_IS_OCTAL_DIGIT (*String)))
    105         {
    106             break;
    107         }
    108 
    109         /* Convert and insert this octal digit into the accumulator */
    110 
    111         Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String);
    112         if (ACPI_FAILURE (Status))
    113         {
    114             Status = AE_OCTAL_OVERFLOW;
    115             break;
    116         }
    117 
    118         String++;
    119     }
    120 
    121     /* Always return the value that has been accumulated */
    122 
    123     *ReturnValuePtr = AccumulatedValue;
    124     return (Status);
    125 }
    126 
    127 
    128 /*******************************************************************************
    129  *
    130  * FUNCTION:    AcpiUtConvertDecimalString
    131  *
    132  * PARAMETERS:  String                  - Null terminated input string
    133  *              ReturnValuePtr          - Where the converted value is returned
    134  *
    135  * RETURN:      Status and 64-bit converted integer
    136  *
    137  * DESCRIPTION: Performs a base 10 conversion of the input string to an
    138  *              integer value, either 32 or 64 bits.
    139  *
    140  * NOTE:        Maximum 64-bit unsigned decimal value is 18446744073709551615
    141  *              Maximum 32-bit unsigned decimal value is 4294967295
    142  *
    143  ******************************************************************************/
    144 
    145 ACPI_STATUS
    146 AcpiUtConvertDecimalString (
    147     char                    *String,
    148     UINT64                  *ReturnValuePtr)
    149 {
    150     UINT64                  AccumulatedValue = 0;
    151     ACPI_STATUS             Status = AE_OK;
    152 
    153 
    154     /* Convert each ASCII byte in the input string */
    155 
    156     while (*String)
    157     {
    158         /* Character must be ASCII 0-9, otherwise terminate with no error */
    159 
    160         if (!isdigit (*String))
    161         {
    162            break;
    163         }
    164 
    165         /* Convert and insert this decimal digit into the accumulator */
    166 
    167         Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String);
    168         if (ACPI_FAILURE (Status))
    169         {
    170             Status = AE_DECIMAL_OVERFLOW;
    171             break;
    172         }
    173 
    174         String++;
    175     }
    176 
    177     /* Always return the value that has been accumulated */
    178 
    179     *ReturnValuePtr = AccumulatedValue;
    180     return (Status);
    181 }
    182 
    183 
    184 /*******************************************************************************
    185  *
    186  * FUNCTION:    AcpiUtConvertHexString
    187  *
    188  * PARAMETERS:  String                  - Null terminated input string
    189  *              ReturnValuePtr          - Where the converted value is returned
    190  *
    191  * RETURN:      Status and 64-bit converted integer
    192  *
    193  * DESCRIPTION: Performs a base 16 conversion of the input string to an
    194  *              integer value, either 32 or 64 bits.
    195  *
    196  * NOTE:        Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
    197  *              Maximum 32-bit unsigned hex value is 0xFFFFFFFF
    198  *
    199  ******************************************************************************/
    200 
    201 ACPI_STATUS
    202 AcpiUtConvertHexString (
    203     char                    *String,
    204     UINT64                  *ReturnValuePtr)
    205 {
    206     UINT64                  AccumulatedValue = 0;
    207     ACPI_STATUS             Status = AE_OK;
    208 
    209 
    210     /* Convert each ASCII byte in the input string */
    211 
    212     while (*String)
    213     {
    214         /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */
    215 
    216         if (!isxdigit (*String))
    217         {
    218             break;
    219         }
    220 
    221         /* Convert and insert this hex digit into the accumulator */
    222 
    223         Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String);
    224         if (ACPI_FAILURE (Status))
    225         {
    226             Status = AE_HEX_OVERFLOW;
    227             break;
    228         }
    229 
    230         String++;
    231     }
    232 
    233     /* Always return the value that has been accumulated */
    234 
    235     *ReturnValuePtr = AccumulatedValue;
    236     return (Status);
    237 }
    238 
    239 
    240 /*******************************************************************************
    241  *
    242  * FUNCTION:    AcpiUtRemoveLeadingZeros
    243  *
    244  * PARAMETERS:  String                  - Pointer to input ASCII string
    245  *
    246  * RETURN:      Next character after any leading zeros. This character may be
    247  *              used by the caller to detect end-of-string.
    248  *
    249  * DESCRIPTION: Remove any leading zeros in the input string. Return the
    250  *              next character after the final ASCII zero to enable the caller
    251  *              to check for the end of the string (NULL terminator).
    252  *
    253  ******************************************************************************/
    254 
    255 char
    256 AcpiUtRemoveLeadingZeros (
    257     char                    **String)
    258 {
    259 
    260     while (**String == ACPI_ASCII_ZERO)
    261     {
    262         *String += 1;
    263     }
    264 
    265     return (**String);
    266 }
    267 
    268 
    269 /*******************************************************************************
    270  *
    271  * FUNCTION:    AcpiUtRemoveWhitespace
    272  *
    273  * PARAMETERS:  String                  - Pointer to input ASCII string
    274  *
    275  * RETURN:      Next character after any whitespace. This character may be
    276  *              used by the caller to detect end-of-string.
    277  *
    278  * DESCRIPTION: Remove any leading whitespace in the input string. Return the
    279  *              next character after the final ASCII zero to enable the caller
    280  *              to check for the end of the string (NULL terminator).
    281  *
    282  ******************************************************************************/
    283 
    284 char
    285 AcpiUtRemoveWhitespace (
    286     char                    **String)
    287 {
    288 
    289     while (isspace ((UINT8) **String))
    290     {
    291         *String += 1;
    292     }
    293 
    294     return (**String);
    295 }
    296 
    297 
    298 /*******************************************************************************
    299  *
    300  * FUNCTION:    AcpiUtDetectHexPrefix
    301  *
    302  * PARAMETERS:  String                  - Pointer to input ASCII string
    303  *
    304  * RETURN:      TRUE if a "0x" prefix was found at the start of the string
    305  *
    306  * DESCRIPTION: Detect and remove a hex "0x" prefix
    307  *
    308  ******************************************************************************/
    309 
    310 BOOLEAN
    311 AcpiUtDetectHexPrefix (
    312     char                    **String)
    313 {
    314     char                    *InitialPosition = *String;
    315 
    316     AcpiUtRemoveHexPrefix (String);
    317     if (*String != InitialPosition)
    318     {
    319         return (TRUE); /* String is past leading 0x */
    320     }
    321 
    322     return (FALSE);     /* Not a hex string */
    323 }
    324 
    325 
    326 /*******************************************************************************
    327  *
    328  * FUNCTION:    AcpiUtRemoveHexPrefix
    329  *
    330  * PARAMETERS:  String                  - Pointer to input ASCII string
    331  *
    332  * RETURN:      none
    333  *
    334  * DESCRIPTION: Remove a hex "0x" prefix
    335  *
    336  ******************************************************************************/
    337 
    338 void
    339 AcpiUtRemoveHexPrefix (
    340     char                    **String)
    341 {
    342     if ((**String == ACPI_ASCII_ZERO) &&
    343         (tolower ((int) *(*String + 1)) == 'x'))
    344     {
    345         *String += 2;        /* Go past the leading 0x */
    346     }
    347 }
    348 
    349 
    350 /*******************************************************************************
    351  *
    352  * FUNCTION:    AcpiUtDetectOctalPrefix
    353  *
    354  * PARAMETERS:  String                  - Pointer to input ASCII string
    355  *
    356  * RETURN:      True if an octal "0" prefix was found at the start of the
    357  *              string
    358  *
    359  * DESCRIPTION: Detect and remove an octal prefix (zero)
    360  *
    361  ******************************************************************************/
    362 
    363 BOOLEAN
    364 AcpiUtDetectOctalPrefix (
    365     char                    **String)
    366 {
    367 
    368     if (**String == ACPI_ASCII_ZERO)
    369     {
    370         *String += 1;       /* Go past the leading 0 */
    371         return (TRUE);
    372     }
    373 
    374     return (FALSE);     /* Not an octal string */
    375 }
    376 
    377 
    378 /*******************************************************************************
    379  *
    380  * FUNCTION:    AcpiUtInsertDigit
    381  *
    382  * PARAMETERS:  AccumulatedValue        - Current value of the integer value
    383  *                                        accumulator. The new value is
    384  *                                        returned here.
    385  *              Base                    - Radix, either 8/10/16
    386  *              AsciiDigit              - ASCII single digit to be inserted
    387  *
    388  * RETURN:      Status and result of the convert/insert operation. The only
    389  *              possible returned exception code is numeric overflow of
    390  *              either the multiply or add conversion operations.
    391  *
    392  * DESCRIPTION: Generic conversion and insertion function for all bases:
    393  *
    394  *              1) Multiply the current accumulated/converted value by the
    395  *              base in order to make room for the new character.
    396  *
    397  *              2) Convert the new character to binary and add it to the
    398  *              current accumulated value.
    399  *
    400  *              Note: The only possible exception indicates an integer
    401  *              overflow (AE_NUMERIC_OVERFLOW)
    402  *
    403  ******************************************************************************/
    404 
    405 static ACPI_STATUS
    406 AcpiUtInsertDigit (
    407     UINT64                  *AccumulatedValue,
    408     UINT32                  Base,
    409     int                     AsciiDigit)
    410 {
    411     ACPI_STATUS             Status;
    412     UINT64                  Product;
    413 
    414 
    415      /* Make room in the accumulated value for the incoming digit */
    416 
    417     Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product);
    418     if (ACPI_FAILURE (Status))
    419     {
    420         return (Status);
    421     }
    422 
    423     /* Add in the new digit, and store the sum to the accumulated value */
    424 
    425     Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit),
    426         AccumulatedValue);
    427 
    428     return (Status);
    429 }
    430 
    431 
    432 /*******************************************************************************
    433  *
    434  * FUNCTION:    AcpiUtStrtoulMultiply64
    435  *
    436  * PARAMETERS:  Multiplicand            - Current accumulated converted integer
    437  *              Base                    - Base/Radix
    438  *              OutProduct              - Where the product is returned
    439  *
    440  * RETURN:      Status and 64-bit product
    441  *
    442  * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
    443  *              well as 32-bit overflow if necessary (if the current global
    444  *              integer width is 32).
    445  *
    446  ******************************************************************************/
    447 
    448 static ACPI_STATUS
    449 AcpiUtStrtoulMultiply64 (
    450     UINT64                  Multiplicand,
    451     UINT32                  Base,
    452     UINT64                  *OutProduct)
    453 {
    454     UINT64                  Product;
    455     UINT64                  Quotient;
    456 
    457 
    458     /* Exit if either operand is zero */
    459 
    460     *OutProduct = 0;
    461     if (!Multiplicand || !Base)
    462     {
    463         return (AE_OK);
    464     }
    465 
    466     /*
    467      * Check for 64-bit overflow before the actual multiplication.
    468      *
    469      * Notes: 64-bit division is often not supported on 32-bit platforms
    470      * (it requires a library function), Therefore ACPICA has a local
    471      * 64-bit divide function. Also, Multiplier is currently only used
    472      * as the radix (8/10/16), to the 64/32 divide will always work.
    473      */
    474     AcpiUtShortDivide (ACPI_UINT64_MAX, Base, &Quotient, NULL);
    475     if (Multiplicand > Quotient)
    476     {
    477         return (AE_NUMERIC_OVERFLOW);
    478     }
    479 
    480     Product = Multiplicand * Base;
    481 
    482     /* Check for 32-bit overflow if necessary */
    483 
    484     if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX))
    485     {
    486         return (AE_NUMERIC_OVERFLOW);
    487     }
    488 
    489     *OutProduct = Product;
    490     return (AE_OK);
    491 }
    492 
    493 
    494 /*******************************************************************************
    495  *
    496  * FUNCTION:    AcpiUtStrtoulAdd64
    497  *
    498  * PARAMETERS:  Addend1                 - Current accumulated converted integer
    499  *              Digit                   - New hex value/char
    500  *              OutSum                  - Where sum is returned (Accumulator)
    501  *
    502  * RETURN:      Status and 64-bit sum
    503  *
    504  * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
    505  *              well as 32-bit overflow if necessary (if the current global
    506  *              integer width is 32).
    507  *
    508  ******************************************************************************/
    509 
    510 static ACPI_STATUS
    511 AcpiUtStrtoulAdd64 (
    512     UINT64                  Addend1,
    513     UINT32                  Digit,
    514     UINT64                  *OutSum)
    515 {
    516     UINT64                  Sum;
    517 
    518 
    519     /* Check for 64-bit overflow before the actual addition */
    520 
    521     if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1)))
    522     {
    523         return (AE_NUMERIC_OVERFLOW);
    524     }
    525 
    526     Sum = Addend1 + Digit;
    527 
    528     /* Check for 32-bit overflow if necessary */
    529 
    530     if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX))
    531     {
    532         return (AE_NUMERIC_OVERFLOW);
    533     }
    534 
    535     *OutSum = Sum;
    536     return (AE_OK);
    537 }
    538