Home | History | Annotate | Line # | Download | only in utilities
utstrtoul64.c revision 1.1
      1 /*******************************************************************************
      2  *
      3  * Module Name: utstrtoul64 - string to 64-bit integer support
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 
     48 /*******************************************************************************
     49  *
     50  * The functions in this module satisfy the need for 64-bit string-to-integer
     51  * conversions on both 32-bit and 64-bit platforms.
     52  *
     53  ******************************************************************************/
     54 
     55 #define _COMPONENT          ACPI_UTILITIES
     56         ACPI_MODULE_NAME    ("utstrtoul64")
     57 
     58 /* Local prototypes */
     59 
     60 static UINT64
     61 AcpiUtStrtoulBase10 (
     62     char                    *String,
     63     UINT32                  Flags);
     64 
     65 static UINT64
     66 AcpiUtStrtoulBase16 (
     67     char                    *String,
     68     UINT32                  Flags);
     69 
     70 
     71 /*******************************************************************************
     72  *
     73  * String conversion rules as written in the ACPI specification. The error
     74  * conditions and behavior are different depending on the type of conversion.
     75  *
     76  *
     77  * Implicit data type conversion: string-to-integer
     78  * --------------------------------------------------
     79  *
     80  * Base is always 16. This is the ACPI_STRTOUL_BASE16 case.
     81  *
     82  * Example:
     83  *      Add ("BA98", Arg0, Local0)
     84  *
     85  * The integer is initialized to the value zero.
     86  * The ASCII string is interpreted as a hexadecimal constant.
     87  *
     88  *  1)  A "0x" prefix is not allowed. However, ACPICA allows this for
     89  *      compatibility with previous ACPICA. (NO ERROR)
     90  *
     91  *  2)  Terminates when the size of an integer is reached (32 or 64 bits).
     92  *      (NO ERROR)
     93  *
     94  *  3)  The first non-hex character terminates the conversion without error.
     95  *      (NO ERROR)
     96  *
     97  *  4)  Conversion of a null (zero-length) string to an integer is not
     98  *      allowed. However, ACPICA allows this for compatibility with previous
     99  *      ACPICA. This conversion returns the value 0. (NO ERROR)
    100  *
    101  *
    102  * Explicit data type conversion:  ToInteger() with string operand
    103  * ---------------------------------------------------------------
    104  *
    105  * Base is either 10 (default) or 16 (with 0x prefix)
    106  *
    107  * Examples:
    108  *      ToInteger ("1000")
    109  *      ToInteger ("0xABCD")
    110  *
    111  *  1)  Can be (must be) either a decimal or hexadecimal numeric string.
    112  *      A hex value must be prefixed by "0x" or it is interpreted as a decimal.
    113  *
    114  *  2)  The value must not exceed the maximum of an integer value. ACPI spec
    115  *      states the behavior is "unpredictable", so ACPICA matches the behavior
    116  *      of the implicit conversion case.(NO ERROR)
    117  *
    118  *  3)  Behavior on the first non-hex character is not specified by the ACPI
    119  *      spec, so ACPICA matches the behavior of the implicit conversion case
    120  *      and terminates. (NO ERROR)
    121  *
    122  *  4)  A null (zero-length) string is illegal.
    123  *      However, ACPICA allows this for compatibility with previous ACPICA.
    124  *      This conversion returns the value 0. (NO ERROR)
    125  *
    126  ******************************************************************************/
    127 
    128 
    129 /*******************************************************************************
    130  *
    131  * FUNCTION:    AcpiUtStrtoul64
    132  *
    133  * PARAMETERS:  String                  - Null terminated input string
    134  *              Flags                   - Conversion info, see below
    135  *              ReturnValue             - Where the converted integer is
    136  *                                        returned
    137  *
    138  * RETURN:      Status and Converted value
    139  *
    140  * DESCRIPTION: Convert a string into an unsigned value. Performs either a
    141  *              32-bit or 64-bit conversion, depending on the input integer
    142  *              size in Flags (often the current mode of the interpreter).
    143  *
    144  * Values for Flags:
    145  *      ACPI_STRTOUL_32BIT      - Max integer value is 32 bits
    146  *      ACPI_STRTOUL_64BIT      - Max integer value is 64 bits
    147  *      ACPI_STRTOUL_BASE16     - Input string is hexadecimal. Default
    148  *                                is 10/16 based on string prefix (0x).
    149  *
    150  * NOTES:
    151  *   Negative numbers are not supported, as they are not supported by ACPI.
    152  *
    153  *   Supports only base 16 or base 10 strings/values. Does not
    154  *   support Octal strings, as these are not supported by ACPI.
    155  *
    156  * Current users of this support:
    157  *
    158  *  Interpreter - Implicit and explicit conversions, GPE method names
    159  *  Debugger    - Command line input string conversion
    160  *  iASL        - Main parser, conversion of constants to integers
    161  *  iASL        - Data Table Compiler parser (constant math expressions)
    162  *  iASL        - Preprocessor (constant math expressions)
    163  *  AcpiDump    - Input table addresses
    164  *  AcpiExec    - Testing of the AcpiUtStrtoul64 function
    165  *
    166  * Note concerning callers:
    167  *   AcpiGbl_IntegerByteWidth can be used to set the 32/64 limit. If used,
    168  *   this global should be set to the proper width. For the core ACPICA code,
    169  *   this width depends on the DSDT version. For iASL, the default byte
    170  *   width is always 8 for the parser, but error checking is performed later
    171  *   to flag cases where a 64-bit constant is defined in a 32-bit DSDT/SSDT.
    172  *
    173  ******************************************************************************/
    174 
    175 ACPI_STATUS
    176 AcpiUtStrtoul64 (
    177     char                    *String,
    178     UINT32                  Flags,
    179     UINT64                  *ReturnValue)
    180 {
    181     ACPI_STATUS             Status = AE_OK;
    182     UINT32                  Base;
    183 
    184 
    185     ACPI_FUNCTION_TRACE_STR (UtStrtoul64, String);
    186 
    187 
    188     /* Parameter validation */
    189 
    190     if (!String || !ReturnValue)
    191     {
    192         return_ACPI_STATUS (AE_BAD_PARAMETER);
    193     }
    194 
    195     *ReturnValue = 0;
    196 
    197     /* Check for zero-length string, returns 0 */
    198 
    199     if (*String == 0)
    200     {
    201         return_ACPI_STATUS (AE_OK);
    202     }
    203 
    204     /* Skip over any white space at start of string */
    205 
    206     while (isspace ((int) *String))
    207     {
    208         String++;
    209     }
    210 
    211     /* End of string? return 0 */
    212 
    213     if (*String == 0)
    214     {
    215         return_ACPI_STATUS (AE_OK);
    216     }
    217 
    218     /*
    219      * 1) The "0x" prefix indicates base 16. Per the ACPI specification,
    220      * the "0x" prefix is only allowed for implicit (non-strict) conversions.
    221      * However, we always allow it for compatibility with older ACPICA.
    222      */
    223     if ((*String == ACPI_ASCII_ZERO) &&
    224         (tolower ((int) *(String + 1)) == 'x'))
    225     {
    226         String += 2;    /* Go past the 0x */
    227         if (*String == 0)
    228         {
    229             return_ACPI_STATUS (AE_OK);     /* Return value 0 */
    230         }
    231 
    232         Base = 16;
    233     }
    234 
    235     /* 2) Force to base 16 (implicit conversion case) */
    236 
    237     else if (Flags & ACPI_STRTOUL_BASE16)
    238     {
    239         Base = 16;
    240     }
    241 
    242     /* 3) Default fallback is to Base 10 */
    243 
    244     else
    245     {
    246         Base = 10;
    247     }
    248 
    249     /* Skip all leading zeros */
    250 
    251     while (*String == ACPI_ASCII_ZERO)
    252     {
    253         String++;
    254         if (*String == 0)
    255         {
    256             return_ACPI_STATUS (AE_OK);     /* Return value 0 */
    257         }
    258     }
    259 
    260     /* Perform the base 16 or 10 conversion */
    261 
    262     if (Base == 16)
    263     {
    264         *ReturnValue = AcpiUtStrtoulBase16 (String, Flags);
    265     }
    266     else
    267     {
    268         *ReturnValue = AcpiUtStrtoulBase10 (String, Flags);
    269     }
    270 
    271     return_ACPI_STATUS (Status);
    272 }
    273 
    274 
    275 /*******************************************************************************
    276  *
    277  * FUNCTION:    AcpiUtStrtoulBase10
    278  *
    279  * PARAMETERS:  String                  - Null terminated input string
    280  *              Flags                   - Conversion info
    281  *
    282  * RETURN:      64-bit converted integer
    283  *
    284  * DESCRIPTION: Performs a base 10 conversion of the input string to an
    285  *              integer value, either 32 or 64 bits.
    286  *              Note: String must be valid and non-null.
    287  *
    288  ******************************************************************************/
    289 
    290 static UINT64
    291 AcpiUtStrtoulBase10 (
    292     char                    *String,
    293     UINT32                  Flags)
    294 {
    295     int                     AsciiDigit;
    296     UINT64                  NextValue;
    297     UINT64                  ReturnValue = 0;
    298 
    299 
    300     /* Main loop: convert each ASCII byte in the input string */
    301 
    302     while (*String)
    303     {
    304         AsciiDigit = *String;
    305         if (!isdigit (AsciiDigit))
    306         {
    307             /* Not ASCII 0-9, terminate */
    308 
    309             goto Exit;
    310         }
    311 
    312         /* Convert and insert (add) the decimal digit */
    313 
    314         NextValue =
    315             (ReturnValue * 10) + (AsciiDigit - ACPI_ASCII_ZERO);
    316 
    317         /* Check for overflow (32 or 64 bit) - return current converted value */
    318 
    319         if (((Flags & ACPI_STRTOUL_32BIT) && (NextValue > ACPI_UINT32_MAX)) ||
    320             (NextValue < ReturnValue)) /* 64-bit overflow case */
    321         {
    322             goto Exit;
    323         }
    324 
    325         ReturnValue = NextValue;
    326         String++;
    327     }
    328 
    329 Exit:
    330     return (ReturnValue);
    331 }
    332 
    333 
    334 /*******************************************************************************
    335  *
    336  * FUNCTION:    AcpiUtStrtoulBase16
    337  *
    338  * PARAMETERS:  String                  - Null terminated input string
    339  *              Flags                   - conversion info
    340  *
    341  * RETURN:      64-bit converted integer
    342  *
    343  * DESCRIPTION: Performs a base 16 conversion of the input string to an
    344  *              integer value, either 32 or 64 bits.
    345  *              Note: String must be valid and non-null.
    346  *
    347  ******************************************************************************/
    348 
    349 static UINT64
    350 AcpiUtStrtoulBase16 (
    351     char                    *String,
    352     UINT32                  Flags)
    353 {
    354     int                     AsciiDigit;
    355     UINT32                  ValidDigits = 1;
    356     UINT64                  ReturnValue = 0;
    357 
    358 
    359     /* Main loop: convert each ASCII byte in the input string */
    360 
    361     while (*String)
    362     {
    363         /* Check for overflow (32 or 64 bit) - return current converted value */
    364 
    365         if ((ValidDigits > 16) ||
    366             ((ValidDigits > 8) && (Flags & ACPI_STRTOUL_32BIT)))
    367         {
    368             goto Exit;
    369         }
    370 
    371         AsciiDigit = *String;
    372         if (!isxdigit (AsciiDigit))
    373         {
    374             /* Not Hex ASCII A-F, a-f, or 0-9, terminate */
    375 
    376             goto Exit;
    377         }
    378 
    379         /* Convert and insert the hex digit */
    380 
    381         ReturnValue =
    382             (ReturnValue << 4) | AcpiUtAsciiCharToHex (AsciiDigit);
    383 
    384         String++;
    385         ValidDigits++;
    386     }
    387 
    388 Exit:
    389     return (ReturnValue);
    390 }
    391