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