diff options
Diffstat (limited to 'source/components/utilities/utnonansi.c')
-rw-r--r-- | source/components/utilities/utnonansi.c | 449 |
1 files changed, 293 insertions, 156 deletions
diff --git a/source/components/utilities/utnonansi.c b/source/components/utilities/utnonansi.c index aea4cfc1b..1e6512ea2 100644 --- a/source/components/utilities/utnonansi.c +++ b/source/components/utilities/utnonansi.c @@ -120,20 +120,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utnonansi") -/* Local prototypes */ - -static ACPI_STATUS -AcpiUtStrtoulBase10 ( - char *String, - UINT32 MaxIntegerByteWidth, - UINT64 *RetInteger); - -static ACPI_STATUS -AcpiUtStrtoulBase16 ( - char *String, - UINT32 MaxIntegerByteWidth, - UINT64 *RetInteger); - /* * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit @@ -330,10 +316,10 @@ AcpiUtSafeStrncat ( * * FUNCTION: AcpiUtStrtoul64 * - * PARAMETERS: String - Null terminated input string + * PARAMETERS: String - Null terminated string * Base - Radix of the string: 16 or 10 or * ACPI_ANY_BASE - * MaxIntegerByteWidth - Maximum allowable integer, in bytes: + * MaxIntegerByteWidth - Maximum allowable integer,in bytes: * 4 or 8 (32 or 64 bits) * RetInteger - Where the converted integer is * returned @@ -347,24 +333,13 @@ AcpiUtSafeStrncat ( * NOTES: Negative numbers are not supported, as they are not supported * by ACPI. * - * Supports only base 16 or base 10 strings/values. Does not - * support Octal strings, not needed at this time. - * * AcpiGbl_IntegerByteWidth should be set to the proper width. * For the core ACPICA code, this width depends on the DSDT * version. For iASL, the default byte width is always 8 for the * parser, but error checking is performed later to flag cases * where a 64-bit constant is defined in a 32-bit DSDT/SSDT. * - * Unlike Clib, this function aborts with an error for any - * malformed input string. - * - * Currently used by: - * iASL/Preprocessor - Expression evaluation - * iASL/DataTableCompiler - Expression evaluation - * Debugger - input string conversion - * Interpreter - Implicit and explicit conversions - * Tools - acpidump, acpiexec + * Does not support Octal strings, not needed at this time. * ******************************************************************************/ @@ -375,52 +350,58 @@ AcpiUtStrtoul64 ( UINT32 MaxIntegerByteWidth, UINT64 *RetInteger) { - ACPI_FUNCTION_TRACE_STR (UtStrtoul64, String); + UINT32 ThisDigit = 0; + UINT64 ReturnValue = 0; + UINT64 Quotient; + UINT64 Dividend; + UINT8 ValidDigits = 0; + UINT8 SignOf0x = 0; + UINT8 Term = 0; - /* Parameter validation */ + ACPI_FUNCTION_TRACE_STR (UtStrtoul64, String); - if (!String || !RetInteger) - { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - if ((Base != ACPI_ANY_BASE) && - (Base != 10) && - (Base != 16)) + switch (Base) { + case ACPI_ANY_BASE: + case 10: + case 16: + + break; + + default: + /* Invalid Base */ return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Skip over any white space at start of string */ - - while (isspace ((int) *String)) + if (!String) { - String++; + goto ErrorExit; } - if (*String == 0) + /* Skip over any white space in the buffer */ + + while ((*String) && (isspace ((int) *String) || *String == '\t')) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + String++; } - /* Determine base if necessary (10 or 16) */ - if (Base == ACPI_ANY_BASE) { /* - * (Base == ACPI_ANY_BASE) means "Either decimal or hex"; - * determine which one. - * NOTE: there is no octal or arbitary base support. + * Base equal to ACPI_ANY_BASE means 'Either decimal or hex'. + * We need to determine if it is decimal or hexadecimal. */ - if ((*String == '0') && - (tolower ((int) *(String + 1)) == 'x')) + if ((*String == '0') && (tolower ((int) *(String + 1)) == 'x')) { - /* Found a "0x" prefix -- the string is hex */ - + SignOf0x = 1; Base = 16; + + /* Skip over the leading '0x' */ + String += 2; } else { @@ -428,175 +409,331 @@ AcpiUtStrtoul64 ( } } - /* Perform the base 16 or 10 conversion */ + /* Any string left? Check that '0x' is not followed by white space. */ - if (Base == 16) + if (!(*String) || isspace ((int) *String) || *String == '\t') { - return (AcpiUtStrtoulBase16 (String, MaxIntegerByteWidth, RetInteger)); - } - else - { - return (AcpiUtStrtoulBase10 (String, MaxIntegerByteWidth, RetInteger)); + if (Base == ACPI_ANY_BASE) + { + goto ErrorExit; + } + else + { + goto AllDone; + } } -} + /* + * Perform a 32-bit or 64-bit conversion, depending upon the input + * byte width + */ + Dividend = (MaxIntegerByteWidth <= ACPI_MAX32_BYTE_WIDTH) ? + ACPI_UINT32_MAX : ACPI_UINT64_MAX; -/******************************************************************************* - * - * FUNCTION: AcpiUtStrtoulBase10 - * - * PARAMETERS: String - Null terminated input string - * MaxIntegerByteWidth - Maximum allowable integer, in bytes: - * 4 or 8 (32 or 64 bits) - * RetInteger - Where the converted integer is - * returned - * - * RETURN: Status - * - * DESCRIPTION: Performs a base 10 conversion of the input string to an - * integer value, either 32 or 64 bits. - * Note: String must be valid and non-null. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiUtStrtoulBase10 ( - char *String, - UINT32 MaxIntegerByteWidth, - UINT64 *RetInteger) -{ - UINT32 ThisDigit; - UINT32 ValidDigits = 0; - UINT64 ReturnValue = 0; - UINT64 NextValue; - - - /* Main loop: convert each ASCII byte in the input string */ + /* Main loop: convert the string to a 32- or 64-bit integer */ while (*String) { - /* Skip all leading zeros */ + if (isdigit ((int) *String)) + { + /* Convert ASCII 0-9 to Decimal value */ + + ThisDigit = ((UINT8) *String) - '0'; + } + else if (Base == 10) + { + /* Digit is out of range; possible in ToInteger case only */ - if ((ValidDigits == 0) && (*String == ACPI_ASCII_ZERO)) + Term = 1; + } + else { + ThisDigit = (UINT8) toupper ((int) *String); + if (isxdigit ((int) ThisDigit)) + { + /* Convert ASCII Hex char to value */ + + ThisDigit = ThisDigit - 'A' + 10; + } + else + { + Term = 1; + } + } + + if (Term) + { + if (Base == ACPI_ANY_BASE) + { + goto ErrorExit; + } + else + { + break; + } + } + else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x) + { + /* Skip zeros */ String++; continue; } - ThisDigit = (UINT8) toupper ((int) *String); - if (!isdigit ((int) ThisDigit)) - { - /* Not ASCII 0-9, terminate */ + ValidDigits++; - return (AE_BAD_DECIMAL_CONSTANT); + if (SignOf0x && ((ValidDigits > 16) || + ((ValidDigits > 8) && (MaxIntegerByteWidth <= ACPI_MAX32_BYTE_WIDTH)))) + { + /* + * This is ToInteger operation case. + * No restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto ErrorExit; } - /* Convert and insert(add) the decimal digit */ - - NextValue = (ReturnValue * 10) + (ThisDigit - '0'); + /* Divide the digit into the correct position */ - /* Check for overflow (32 or 64 bit) */ + (void) AcpiUtShortDivide ( + (Dividend - (UINT64) ThisDigit), Base, &Quotient, NULL); - if (((MaxIntegerByteWidth <= ACPI_MAX32_BYTE_WIDTH) && - (NextValue > ACPI_UINT32_MAX)) || - (NextValue < ReturnValue)) /* 64-bit overflow case */ + if (ReturnValue > Quotient) { - return (AE_CONVERSION_OVERFLOW); + if (Base == ACPI_ANY_BASE) + { + goto ErrorExit; + } + else + { + break; + } } - ReturnValue = NextValue; + ReturnValue *= Base; + ReturnValue += ThisDigit; String++; - ValidDigits++; } + /* All done, normal exit */ + +AllDone: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ReturnValue))); + *RetInteger = ReturnValue; - return (AE_OK); + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + + /* Base was set/validated above (10 or 16) */ + + if (Base == 10) + { + return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); + } + else + { + return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); + } } +#ifdef _OBSOLETE_FUNCTIONS +/* Removed: 01/2016 */ + /******************************************************************************* * - * FUNCTION: AcpiUtStrtoulBase16 + * FUNCTION: strtoul64 * - * PARAMETERS: String - Null terminated input string - * MaxIntegerByteWidth - Maximum allowable integer, in bytes: - * 4 or 8 (32 or 64 bits) - * RetInteger - Where the converted integer is - * returned + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte + * is returned + * Base - Radix of the string * - * RETURN: Status + * RETURN: Converted value * - * DESCRIPTION: Performs a base 16 conversion of the input string to an - * integer value, either 32 or 64 bits. - * Note: String must be valid and non-null. + * DESCRIPTION: Convert a string into an unsigned value. * ******************************************************************************/ -static ACPI_STATUS -AcpiUtStrtoulBase16 ( +ACPI_STATUS +strtoul64 ( char *String, - UINT32 MaxIntegerByteWidth, + UINT32 Base, UINT64 *RetInteger) { - UINT32 ThisDigit; - UINT32 ValidDigits = 0; + UINT32 Index; + UINT32 Sign; UINT64 ReturnValue = 0; + ACPI_STATUS Status = AE_OK; + + + *RetInteger = 0; + + switch (Base) + { + case 0: + case 8: + case 10: + case 16: + + break; + + default: + /* + * The specified Base parameter is not in the domain of + * this function: + */ + return (AE_BAD_PARAMETER); + } + /* Skip over any white space in the buffer: */ + + while (isspace ((int) *String) || *String == '\t') + { + ++String; + } - /* Allow "0x" prefix for all hex constants */ + /* + * The buffer may contain an optional plus or minus sign. + * If it does, then skip over it but remember what is was: + */ + if (*String == '-') + { + Sign = ACPI_SIGN_NEGATIVE; + ++String; + } + else if (*String == '+') + { + ++String; + Sign = ACPI_SIGN_POSITIVE; + } + else + { + Sign = ACPI_SIGN_POSITIVE; + } - if ((*String == '0') && - (tolower ((int) *(String + 1)) == 'x')) + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (Base == 0) { - String += 2; /* Go past the 0x */ - if (*String == 0) + if (*String == '0') + { + if (tolower ((int) *(++String)) == 'x') + { + Base = 16; + ++String; + } + else + { + Base = 8; + } + } + else { - return (AE_BAD_HEX_CONSTANT); + Base = 10; } } - /* Main loop: convert each ASCII byte in the input string */ + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (Base == 8 && *String == '0') + { + String++; + } + + if (Base == 16 && + *String == '0' && + tolower ((int) *(++String)) == 'x') + { + String++; + } + + /* Main loop: convert the string to an unsigned long */ while (*String) { - /* Skip all leading zeros */ + if (isdigit ((int) *String)) + { + Index = ((UINT8) *String) - '0'; + } + else + { + Index = (UINT8) toupper ((int) *String); + if (isupper ((int) Index)) + { + Index = Index - 'A' + 10; + } + else + { + goto ErrorExit; + } + } - if ((ValidDigits == 0) && (*String == ACPI_ASCII_ZERO)) + if (Index >= Base) { - String++; - continue; + goto ErrorExit; } - /* Check for overflow (32 or 64 bit) */ + /* Check to see if value is out of range: */ - if ((ValidDigits > 16) || - ((ValidDigits > 8) && (MaxIntegerByteWidth <= ACPI_MAX32_BYTE_WIDTH))) + if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) / + (UINT64) Base)) { - /* - * This is ToInteger operation case. - * No restrictions for string-to-integer conversion, - * see ACPI spec. - */ - return (AE_CONVERSION_OVERFLOW); + goto ErrorExit; } - - ThisDigit = (UINT8) toupper ((int) *String); - if (!isxdigit ((int) ThisDigit)) + else { - /* Not Hex ASCII A-F or 0-9, terminate */ - - return (AE_BAD_HEX_CONSTANT); + ReturnValue *= Base; + ReturnValue += Index; } - /* Convert and insert the hex digit */ + ++String; + } - ThisDigit = AcpiUtAsciiCharToHex (ThisDigit); - ReturnValue = (ReturnValue << 4) | ThisDigit; - String++; - ValidDigits++; + /* If a minus sign was present, then "the conversion is negated": */ + + if (Sign == ACPI_SIGN_NEGATIVE) + { + ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; } *RetInteger = ReturnValue; - return (AE_OK); + return (Status); + + +ErrorExit: + switch (Base) + { + case 8: + + Status = AE_BAD_OCTAL_CONSTANT; + break; + + case 10: + + Status = AE_BAD_DECIMAL_CONSTANT; + break; + + case 16: + + Status = AE_BAD_HEX_CONSTANT; + break; + + default: + + /* Base validated above */ + + break; + } + + return (Status); } +#endif |