Home | History | Annotate | Line # | Download | only in compiler
aslutils.c revision 1.4.12.2
      1 /******************************************************************************
      2  *
      3  * Module Name: aslutils -- compiler utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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 
     45 #include "aslcompiler.h"
     46 #include "aslcompiler.y.h"
     47 #include "acdisasm.h"
     48 #include "acnamesp.h"
     49 #include "amlcode.h"
     50 #include <acapps.h>
     51 
     52 #define _COMPONENT          ACPI_COMPILER
     53         ACPI_MODULE_NAME    ("aslutils")
     54 
     55 
     56 /* Local prototypes */
     57 
     58 static void
     59 UtPadNameWithUnderscores (
     60     char                    *NameSeg,
     61     char                    *PaddedNameSeg);
     62 
     63 static void
     64 UtAttachNameseg (
     65     ACPI_PARSE_OBJECT       *Op,
     66     char                    *Name);
     67 
     68 
     69 /*******************************************************************************
     70  *
     71  * FUNCTION:    UtDisplaySupportedTables
     72  *
     73  * PARAMETERS:  None
     74  *
     75  * RETURN:      None
     76  *
     77  * DESCRIPTION: Print all supported ACPI table names.
     78  *
     79  ******************************************************************************/
     80 
     81 #define ACPI_TABLE_HELP_FORMAT  "%8u) %s    %s\n"
     82 
     83 void
     84 UtDisplaySupportedTables (
     85     void)
     86 {
     87     ACPI_DMTABLE_DATA       *TableData;
     88     UINT32                  i;
     89 
     90 
     91     printf ("\nACPI tables supported by iASL version %8.8X:\n"
     92         "  (Compiler, Disassembler, Template Generator)\n\n",
     93         ACPI_CA_VERSION);
     94 
     95     /* Special tables */
     96 
     97     printf ("  Special tables and AML tables:\n");
     98     printf (ACPI_TABLE_HELP_FORMAT, 1, ACPI_RSDP_NAME, "Root System Description Pointer");
     99     printf (ACPI_TABLE_HELP_FORMAT, 2, ACPI_SIG_FACS, "Firmware ACPI Control Structure");
    100     printf (ACPI_TABLE_HELP_FORMAT, 3, ACPI_SIG_DSDT, "Differentiated System Description Table");
    101     printf (ACPI_TABLE_HELP_FORMAT, 4, ACPI_SIG_SSDT, "Secondary System Description Table");
    102 
    103     /* All data tables with common table header */
    104 
    105     printf ("\n  Standard ACPI data tables:\n");
    106     for (TableData = AcpiDmTableData, i = 5; TableData->Signature; TableData++, i++)
    107     {
    108         printf (ACPI_TABLE_HELP_FORMAT, i, TableData->Signature, TableData->Name);
    109     }
    110 }
    111 
    112 
    113 /*******************************************************************************
    114  *
    115  * FUNCTION:    UtDisplayConstantOpcodes
    116  *
    117  * PARAMETERS:  None
    118  *
    119  * RETURN:      None
    120  *
    121  * DESCRIPTION: Print AML opcodes that can be used in constant expressions.
    122  *
    123  ******************************************************************************/
    124 
    125 void
    126 UtDisplayConstantOpcodes (
    127     void)
    128 {
    129     UINT32                  i;
    130 
    131 
    132     printf ("Constant expression opcode information\n\n");
    133 
    134     for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++)
    135     {
    136         if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT)
    137         {
    138             printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name);
    139         }
    140     }
    141 }
    142 
    143 
    144 /*******************************************************************************
    145  *
    146  * FUNCTION:    UtLocalCalloc
    147  *
    148  * PARAMETERS:  Size                - Bytes to be allocated
    149  *
    150  * RETURN:      Pointer to the allocated memory. Guaranteed to be valid.
    151  *
    152  * DESCRIPTION: Allocate zero-initialized memory. Aborts the compile on an
    153  *              allocation failure, on the assumption that nothing more can be
    154  *              accomplished.
    155  *
    156  ******************************************************************************/
    157 
    158 void *
    159 UtLocalCalloc (
    160     UINT32                  Size)
    161 {
    162     void                    *Allocated;
    163 
    164 
    165     Allocated = ACPI_ALLOCATE_ZEROED (Size);
    166     if (!Allocated)
    167     {
    168         AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION,
    169             Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
    170             Gbl_InputByteCount, Gbl_CurrentColumn,
    171             Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
    172 
    173         CmCleanupAndExit ();
    174         exit (1);
    175     }
    176 
    177     TotalAllocations++;
    178     TotalAllocated += Size;
    179     return (Allocated);
    180 }
    181 
    182 
    183 /*******************************************************************************
    184  *
    185  * FUNCTION:    UtBeginEvent
    186  *
    187  * PARAMETERS:  Name                - Ascii name of this event
    188  *
    189  * RETURN:      Event number (integer index)
    190  *
    191  * DESCRIPTION: Saves the current time with this event
    192  *
    193  ******************************************************************************/
    194 
    195 UINT8
    196 UtBeginEvent (
    197     char                    *Name)
    198 {
    199 
    200     if (AslGbl_NextEvent >= ASL_NUM_EVENTS)
    201     {
    202         AcpiOsPrintf ("Ran out of compiler event structs!\n");
    203         return (AslGbl_NextEvent);
    204     }
    205 
    206     /* Init event with current (start) time */
    207 
    208     AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer ();
    209     AslGbl_Events[AslGbl_NextEvent].EventName = Name;
    210     AslGbl_Events[AslGbl_NextEvent].Valid = TRUE;
    211 
    212     return (AslGbl_NextEvent++);
    213 }
    214 
    215 
    216 /*******************************************************************************
    217  *
    218  * FUNCTION:    UtEndEvent
    219  *
    220  * PARAMETERS:  Event               - Event number (integer index)
    221  *
    222  * RETURN:      None
    223  *
    224  * DESCRIPTION: Saves the current time (end time) with this event
    225  *
    226  ******************************************************************************/
    227 
    228 void
    229 UtEndEvent (
    230     UINT8                   Event)
    231 {
    232 
    233     if (Event >= ASL_NUM_EVENTS)
    234     {
    235         return;
    236     }
    237 
    238     /* Insert end time for event */
    239 
    240     AslGbl_Events[Event].EndTime = AcpiOsGetTimer ();
    241 }
    242 
    243 
    244 /*******************************************************************************
    245  *
    246  * FUNCTION:    UtHexCharToValue
    247  *
    248  * PARAMETERS:  HexChar             - Hex character in Ascii
    249  *
    250  * RETURN:      The binary value of the hex character
    251  *
    252  * DESCRIPTION: Perform ascii-to-hex translation
    253  *
    254  ******************************************************************************/
    255 
    256 UINT8
    257 UtHexCharToValue (
    258     int                     HexChar)
    259 {
    260 
    261     if (HexChar <= 0x39)
    262     {
    263         return ((UINT8) (HexChar - 0x30));
    264     }
    265 
    266     if (HexChar <= 0x46)
    267     {
    268         return ((UINT8) (HexChar - 0x37));
    269     }
    270 
    271     return ((UINT8) (HexChar - 0x57));
    272 }
    273 
    274 
    275 /*******************************************************************************
    276  *
    277  * FUNCTION:    UtConvertByteToHex
    278  *
    279  * PARAMETERS:  RawByte             - Binary data
    280  *              Buffer              - Pointer to where the hex bytes will be
    281  *                                    stored
    282  *
    283  * RETURN:      Ascii hex byte is stored in Buffer.
    284  *
    285  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
    286  *              with "0x"
    287  *
    288  ******************************************************************************/
    289 
    290 void
    291 UtConvertByteToHex (
    292     UINT8                   RawByte,
    293     UINT8                   *Buffer)
    294 {
    295 
    296     Buffer[0] = '0';
    297     Buffer[1] = 'x';
    298 
    299     Buffer[2] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF];
    300     Buffer[3] = (UINT8) AslHexLookup[RawByte & 0xF];
    301 }
    302 
    303 
    304 /*******************************************************************************
    305  *
    306  * FUNCTION:    UtConvertByteToAsmHex
    307  *
    308  * PARAMETERS:  RawByte             - Binary data
    309  *              Buffer              - Pointer to where the hex bytes will be
    310  *                                    stored
    311  *
    312  * RETURN:      Ascii hex byte is stored in Buffer.
    313  *
    314  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
    315  *              with "0x"
    316  *
    317  ******************************************************************************/
    318 
    319 void
    320 UtConvertByteToAsmHex (
    321     UINT8                   RawByte,
    322     UINT8                   *Buffer)
    323 {
    324 
    325     Buffer[0] = '0';
    326     Buffer[1] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF];
    327     Buffer[2] = (UINT8) AslHexLookup[RawByte & 0xF];
    328     Buffer[3] = 'h';
    329 }
    330 
    331 
    332 /*******************************************************************************
    333  *
    334  * FUNCTION:    DbgPrint
    335  *
    336  * PARAMETERS:  Type                - Type of output
    337  *              Fmt                 - Printf format string
    338  *              ...                 - variable printf list
    339  *
    340  * RETURN:      None
    341  *
    342  * DESCRIPTION: Conditional print statement. Prints to stderr only if the
    343  *              debug flag is set.
    344  *
    345  ******************************************************************************/
    346 
    347 void
    348 DbgPrint (
    349     UINT32                  Type,
    350     char                    *Fmt,
    351     ...)
    352 {
    353     va_list                 Args;
    354 
    355 
    356     if (!Gbl_DebugFlag)
    357     {
    358         return;
    359     }
    360 
    361     if ((Type == ASL_PARSE_OUTPUT) &&
    362         (!(AslCompilerdebug)))
    363     {
    364         return;
    365     }
    366 
    367     va_start (Args, Fmt);
    368     (void) vfprintf (stderr, Fmt, Args);
    369     va_end (Args);
    370     return;
    371 }
    372 
    373 
    374 /*******************************************************************************
    375  *
    376  * FUNCTION:    UtPrintFormattedName
    377  *
    378  * PARAMETERS:  ParseOpcode         - Parser keyword ID
    379  *              Level               - Indentation level
    380  *
    381  * RETURN:      None
    382  *
    383  * DESCRIPTION: Print the ascii name of the parse opcode.
    384  *
    385  ******************************************************************************/
    386 
    387 #define TEXT_OFFSET 10
    388 
    389 void
    390 UtPrintFormattedName (
    391     UINT16                  ParseOpcode,
    392     UINT32                  Level)
    393 {
    394 
    395     if (Level)
    396     {
    397         DbgPrint (ASL_TREE_OUTPUT,
    398             "%*s", (3 * Level), " ");
    399     }
    400     DbgPrint (ASL_TREE_OUTPUT,
    401         " %-20.20s", UtGetOpName (ParseOpcode));
    402 
    403     if (Level < TEXT_OFFSET)
    404     {
    405         DbgPrint (ASL_TREE_OUTPUT,
    406             "%*s", (TEXT_OFFSET - Level) * 3, " ");
    407     }
    408 }
    409 
    410 
    411 /*******************************************************************************
    412  *
    413  * FUNCTION:    UtSetParseOpName
    414  *
    415  * PARAMETERS:  Op                  - Parse op to be named.
    416  *
    417  * RETURN:      None
    418  *
    419  * DESCRIPTION: Insert the ascii name of the parse opcode
    420  *
    421  ******************************************************************************/
    422 
    423 void
    424 UtSetParseOpName (
    425     ACPI_PARSE_OBJECT       *Op)
    426 {
    427 
    428     strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode),
    429         ACPI_MAX_PARSEOP_NAME);
    430 }
    431 
    432 
    433 /*******************************************************************************
    434  *
    435  * FUNCTION:    UtDisplaySummary
    436  *
    437  * PARAMETERS:  FileID              - ID of outpout file
    438  *
    439  * RETURN:      None
    440  *
    441  * DESCRIPTION: Display compilation statistics
    442  *
    443  ******************************************************************************/
    444 
    445 void
    446 UtDisplaySummary (
    447     UINT32                  FileId)
    448 {
    449     UINT32                  i;
    450 
    451 
    452     if (FileId != ASL_FILE_STDOUT)
    453     {
    454         /* Compiler name and version number */
    455 
    456         FlPrintFile (FileId, "%s version %X%s [%s]\n\n",
    457             ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH, ACPI_DATE);
    458     }
    459 
    460     /* Summary of main input and output files */
    461 
    462     if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA)
    463     {
    464         FlPrintFile (FileId,
    465             "%-14s %s - %u lines, %u bytes, %u fields\n",
    466             "Table Input:",
    467             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
    468             Gbl_InputByteCount, Gbl_InputFieldCount);
    469 
    470         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
    471         {
    472             FlPrintFile (FileId,
    473                 "%-14s %s - %u bytes\n",
    474                 "Binary Output:",
    475                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength);
    476         }
    477     }
    478     else
    479     {
    480         FlPrintFile (FileId,
    481             "%-14s %s - %u lines, %u bytes, %u keywords\n",
    482             "ASL Input:",
    483             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
    484             Gbl_InputByteCount, TotalKeywords);
    485 
    486         /* AML summary */
    487 
    488         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
    489         {
    490             FlPrintFile (FileId,
    491                 "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n",
    492                 "AML Output:",
    493                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength,
    494                 TotalNamedObjects, TotalExecutableOpcodes);
    495         }
    496     }
    497 
    498     /* Display summary of any optional files */
    499 
    500     for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
    501     {
    502         if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle)
    503         {
    504             continue;
    505         }
    506 
    507         /* .SRC is a temp file unless specifically requested */
    508 
    509         if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag))
    510         {
    511             continue;
    512         }
    513 
    514         /* .I is a temp file unless specifically requested */
    515 
    516         if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_PreprocessorOutputFlag))
    517         {
    518             continue;
    519         }
    520 
    521         FlPrintFile (FileId, "%14s %s - %u bytes\n",
    522             Gbl_Files[i].ShortDescription,
    523             Gbl_Files[i].Filename, FlGetFileSize (i));
    524     }
    525 
    526     /* Error summary */
    527 
    528     FlPrintFile (FileId,
    529         "\nCompilation complete. %u Errors, %u Warnings, %u Remarks",
    530         Gbl_ExceptionCount[ASL_ERROR],
    531         Gbl_ExceptionCount[ASL_WARNING] +
    532             Gbl_ExceptionCount[ASL_WARNING2] +
    533             Gbl_ExceptionCount[ASL_WARNING3],
    534         Gbl_ExceptionCount[ASL_REMARK]);
    535 
    536     if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
    537     {
    538         FlPrintFile (FileId,
    539             ", %u Optimizations", Gbl_ExceptionCount[ASL_OPTIMIZATION]);
    540     }
    541 
    542     FlPrintFile (FileId, "\n");
    543 }
    544 
    545 
    546 /*******************************************************************************
    547  *
    548  * FUNCTION:    UtCheckIntegerRange
    549  *
    550  * PARAMETERS:  Op                  - Integer parse node
    551  *              LowValue            - Smallest allowed value
    552  *              HighValue           - Largest allowed value
    553  *
    554  * RETURN:      Op if OK, otherwise NULL
    555  *
    556  * DESCRIPTION: Check integer for an allowable range
    557  *
    558  ******************************************************************************/
    559 
    560 ACPI_PARSE_OBJECT *
    561 UtCheckIntegerRange (
    562     ACPI_PARSE_OBJECT       *Op,
    563     UINT32                  LowValue,
    564     UINT32                  HighValue)
    565 {
    566 
    567     if (!Op)
    568     {
    569         return (NULL);
    570     }
    571 
    572     if ((Op->Asl.Value.Integer < LowValue) ||
    573         (Op->Asl.Value.Integer > HighValue))
    574     {
    575         snprintf (MsgBuffer, sizeof(MsgBuffer), "0x%X, allowable: 0x%X-0x%X",
    576             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
    577 
    578         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
    579         return (NULL);
    580     }
    581 
    582     return (Op);
    583 }
    584 
    585 
    586 /*******************************************************************************
    587  *
    588  * FUNCTION:    UtGetStringBuffer
    589  *
    590  * PARAMETERS:  Length              - Size of buffer requested
    591  *
    592  * RETURN:      Pointer to the buffer. Aborts on allocation failure
    593  *
    594  * DESCRIPTION: Allocate a string buffer. Bypass the local
    595  *              dynamic memory manager for performance reasons (This has a
    596  *              major impact on the speed of the compiler.)
    597  *
    598  ******************************************************************************/
    599 
    600 char *
    601 UtGetStringBuffer (
    602     UINT32                  Length)
    603 {
    604     char                    *Buffer;
    605 
    606 
    607     if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast)
    608     {
    609         Gbl_StringCacheNext = UtLocalCalloc (ASL_STRING_CACHE_SIZE + Length);
    610         Gbl_StringCacheLast = Gbl_StringCacheNext + ASL_STRING_CACHE_SIZE +
    611                                 Length;
    612     }
    613 
    614     Buffer = Gbl_StringCacheNext;
    615     Gbl_StringCacheNext += Length;
    616 
    617     return (Buffer);
    618 }
    619 
    620 
    621 /******************************************************************************
    622  *
    623  * FUNCTION:    UtExpandLineBuffers
    624  *
    625  * PARAMETERS:  None. Updates global line buffer pointers.
    626  *
    627  * RETURN:      None. Reallocates the global line buffers
    628  *
    629  * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates
    630  *              all global line buffers and updates Gbl_LineBufferSize. NOTE:
    631  *              Also used for the initial allocation of the buffers, when
    632  *              all of the buffer pointers are NULL. Initial allocations are
    633  *              of size ASL_DEFAULT_LINE_BUFFER_SIZE
    634  *
    635  *****************************************************************************/
    636 
    637 void
    638 UtExpandLineBuffers (
    639     void)
    640 {
    641     UINT32                  NewSize;
    642 
    643 
    644     /* Attempt to double the size of all line buffers */
    645 
    646     NewSize = Gbl_LineBufferSize * 2;
    647     if (Gbl_CurrentLineBuffer)
    648     {
    649         DbgPrint (ASL_DEBUG_OUTPUT,"Increasing line buffer size from %u to %u\n",
    650             Gbl_LineBufferSize, NewSize);
    651     }
    652 
    653     Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize);
    654     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
    655     if (!Gbl_CurrentLineBuffer)
    656     {
    657         goto ErrorExit;
    658     }
    659 
    660     Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize);
    661     if (!Gbl_MainTokenBuffer)
    662     {
    663         goto ErrorExit;
    664     }
    665 
    666     Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize);
    667     if (!Gbl_MacroTokenBuffer)
    668     {
    669         goto ErrorExit;
    670     }
    671 
    672     Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize);
    673     if (!Gbl_ExpressionTokenBuffer)
    674     {
    675         goto ErrorExit;
    676     }
    677 
    678     Gbl_LineBufferSize = NewSize;
    679     return;
    680 
    681 
    682     /* On error above, simply issue error messages and abort, cannot continue */
    683 
    684 ErrorExit:
    685     printf ("Could not increase line buffer size from %u to %u\n",
    686         Gbl_LineBufferSize, Gbl_LineBufferSize * 2);
    687 
    688     AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION,
    689         NULL, NULL);
    690     AslAbort ();
    691 }
    692 
    693 
    694 /*******************************************************************************
    695  *
    696  * FUNCTION:    UtInternalizeName
    697  *
    698  * PARAMETERS:  ExternalName        - Name to convert
    699  *              ConvertedName       - Where the converted name is returned
    700  *
    701  * RETURN:      Status
    702  *
    703  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
    704  *
    705  ******************************************************************************/
    706 
    707 ACPI_STATUS
    708 UtInternalizeName (
    709     char                    *ExternalName,
    710     char                    **ConvertedName)
    711 {
    712     ACPI_NAMESTRING_INFO    Info;
    713     ACPI_STATUS             Status;
    714 
    715 
    716     if (!ExternalName)
    717     {
    718         return (AE_OK);
    719     }
    720 
    721     /* Get the length of the new internal name */
    722 
    723     Info.ExternalName = ExternalName;
    724     AcpiNsGetInternalNameLength (&Info);
    725 
    726     /* We need a segment to store the internal  name */
    727 
    728     Info.InternalName = UtGetStringBuffer (Info.Length);
    729     if (!Info.InternalName)
    730     {
    731         return (AE_NO_MEMORY);
    732     }
    733 
    734     /* Build the name */
    735 
    736     Status = AcpiNsBuildInternalName (&Info);
    737     if (ACPI_FAILURE (Status))
    738     {
    739         return (Status);
    740     }
    741 
    742     *ConvertedName = Info.InternalName;
    743     return (AE_OK);
    744 }
    745 
    746 
    747 /*******************************************************************************
    748  *
    749  * FUNCTION:    UtPadNameWithUnderscores
    750  *
    751  * PARAMETERS:  NameSeg             - Input nameseg
    752  *              PaddedNameSeg       - Output padded nameseg
    753  *
    754  * RETURN:      Padded nameseg.
    755  *
    756  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
    757  *              ACPI_NAME.
    758  *
    759  ******************************************************************************/
    760 
    761 static void
    762 UtPadNameWithUnderscores (
    763     char                    *NameSeg,
    764     char                    *PaddedNameSeg)
    765 {
    766     UINT32                  i;
    767 
    768 
    769     for (i = 0; (i < ACPI_NAME_SIZE); i++)
    770     {
    771         if (*NameSeg)
    772         {
    773             *PaddedNameSeg = *NameSeg;
    774             NameSeg++;
    775         }
    776         else
    777         {
    778             *PaddedNameSeg = '_';
    779         }
    780         PaddedNameSeg++;
    781     }
    782 }
    783 
    784 
    785 /*******************************************************************************
    786  *
    787  * FUNCTION:    UtAttachNameseg
    788  *
    789  * PARAMETERS:  Op                  - Parent parse node
    790  *              Name                - Full ExternalName
    791  *
    792  * RETURN:      None; Sets the NameSeg field in parent node
    793  *
    794  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
    795  *              in the NameSeg field of the Op.
    796  *
    797  ******************************************************************************/
    798 
    799 static void
    800 UtAttachNameseg (
    801     ACPI_PARSE_OBJECT       *Op,
    802     char                    *Name)
    803 {
    804     char                    *NameSeg;
    805     char                    PaddedNameSeg[4];
    806 
    807 
    808     if (!Name)
    809     {
    810         return;
    811     }
    812 
    813     /* Look for the last dot in the namepath */
    814 
    815     NameSeg = strrchr (Name, '.');
    816     if (NameSeg)
    817     {
    818         /* Found last dot, we have also found the final nameseg */
    819 
    820         NameSeg++;
    821         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
    822     }
    823     else
    824     {
    825         /* No dots in the namepath, there is only a single nameseg. */
    826         /* Handle prefixes */
    827 
    828         while (ACPI_IS_ROOT_PREFIX (*Name) ||
    829                ACPI_IS_PARENT_PREFIX (*Name))
    830         {
    831             Name++;
    832         }
    833 
    834         /* Remaining string should be one single nameseg */
    835 
    836         UtPadNameWithUnderscores (Name, PaddedNameSeg);
    837     }
    838 
    839     ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
    840 }
    841 
    842 
    843 /*******************************************************************************
    844  *
    845  * FUNCTION:    UtAttachNamepathToOwner
    846  *
    847  * PARAMETERS:  Op                  - Parent parse node
    848  *              NameOp              - Node that contains the name
    849  *
    850  * RETURN:      Sets the ExternalName and Namepath in the parent node
    851  *
    852  * DESCRIPTION: Store the name in two forms in the parent node: The original
    853  *              (external) name, and the internalized name that is used within
    854  *              the ACPI namespace manager.
    855  *
    856  ******************************************************************************/
    857 
    858 void
    859 UtAttachNamepathToOwner (
    860     ACPI_PARSE_OBJECT       *Op,
    861     ACPI_PARSE_OBJECT       *NameOp)
    862 {
    863     ACPI_STATUS             Status;
    864 
    865 
    866     /* Full external path */
    867 
    868     Op->Asl.ExternalName = NameOp->Asl.Value.String;
    869 
    870     /* Save the NameOp for possible error reporting later */
    871 
    872     Op->Asl.ParentMethod = (void *) NameOp;
    873 
    874     /* Last nameseg of the path */
    875 
    876     UtAttachNameseg (Op, Op->Asl.ExternalName);
    877 
    878     /* Create internalized path */
    879 
    880     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
    881     if (ACPI_FAILURE (Status))
    882     {
    883         /* TBD: abort on no memory */
    884     }
    885 }
    886 
    887 
    888 /*******************************************************************************
    889  *
    890  * FUNCTION:    UtDoConstant
    891  *
    892  * PARAMETERS:  String              - Hex, Octal, or Decimal string
    893  *
    894  * RETURN:      Converted Integer
    895  *
    896  * DESCRIPTION: Convert a string to an integer, with error checking.
    897  *
    898  ******************************************************************************/
    899 
    900 UINT64
    901 UtDoConstant (
    902     char                    *String)
    903 {
    904     ACPI_STATUS             Status;
    905     UINT64                  Converted;
    906     char                    ErrBuf[64];
    907 
    908 
    909     Status = UtStrtoul64 (String, 0, &Converted);
    910     if (ACPI_FAILURE (Status))
    911     {
    912         snprintf (ErrBuf, sizeof(ErrBuf), "%s %s\n", "Conversion error:",
    913             AcpiFormatException (Status));
    914         AslCompilererror (ErrBuf);
    915     }
    916 
    917     return (Converted);
    918 }
    919 
    920 
    921 /* TBD: use version in ACPI CA main code base? */
    922 
    923 /*******************************************************************************
    924  *
    925  * FUNCTION:    UtStrtoul64
    926  *
    927  * PARAMETERS:  String              - Null terminated string
    928  *              Terminater          - Where a pointer to the terminating byte
    929  *                                    is returned
    930  *              Base                - Radix of the string
    931  *
    932  * RETURN:      Converted value
    933  *
    934  * DESCRIPTION: Convert a string into an unsigned value.
    935  *
    936  ******************************************************************************/
    937 
    938 ACPI_STATUS
    939 UtStrtoul64 (
    940     char                    *String,
    941     UINT32                  Base,
    942     UINT64                  *RetInteger)
    943 {
    944     UINT32                  Index;
    945     UINT32                  Sign;
    946     UINT64                  ReturnValue = 0;
    947     ACPI_STATUS             Status = AE_OK;
    948 
    949 
    950     *RetInteger = 0;
    951 
    952     switch (Base)
    953     {
    954     case 0:
    955     case 8:
    956     case 10:
    957     case 16:
    958 
    959         break;
    960 
    961     default:
    962         /*
    963          * The specified Base parameter is not in the domain of
    964          * this function:
    965          */
    966         return (AE_BAD_PARAMETER);
    967     }
    968 
    969     /* Skip over any white space in the buffer: */
    970 
    971     while (isspace ((int) *String) || *String == '\t')
    972     {
    973         ++String;
    974     }
    975 
    976     /*
    977      * The buffer may contain an optional plus or minus sign.
    978      * If it does, then skip over it but remember what is was:
    979      */
    980     if (*String == '-')
    981     {
    982         Sign = NEGATIVE;
    983         ++String;
    984     }
    985     else if (*String == '+')
    986     {
    987         ++String;
    988         Sign = POSITIVE;
    989     }
    990     else
    991     {
    992         Sign = POSITIVE;
    993     }
    994 
    995     /*
    996      * If the input parameter Base is zero, then we need to
    997      * determine if it is octal, decimal, or hexadecimal:
    998      */
    999     if (Base == 0)
   1000     {
   1001         if (*String == '0')
   1002         {
   1003             if (tolower ((int) *(++String)) == 'x')
   1004             {
   1005                 Base = 16;
   1006                 ++String;
   1007             }
   1008             else
   1009             {
   1010                 Base = 8;
   1011             }
   1012         }
   1013         else
   1014         {
   1015             Base = 10;
   1016         }
   1017     }
   1018 
   1019     /*
   1020      * For octal and hexadecimal bases, skip over the leading
   1021      * 0 or 0x, if they are present.
   1022      */
   1023     if (Base == 8 && *String == '0')
   1024     {
   1025         String++;
   1026     }
   1027 
   1028     if (Base == 16 &&
   1029         *String == '0' &&
   1030         tolower ((int) *(++String)) == 'x')
   1031     {
   1032         String++;
   1033     }
   1034 
   1035     /* Main loop: convert the string to an unsigned long */
   1036 
   1037     while (*String)
   1038     {
   1039         if (isdigit ((int) *String))
   1040         {
   1041             Index = ((UINT8) *String) - '0';
   1042         }
   1043         else
   1044         {
   1045             Index = (UINT8) toupper ((int) *String);
   1046             if (isupper ((int) Index))
   1047             {
   1048                 Index = Index - 'A' + 10;
   1049             }
   1050             else
   1051             {
   1052                 goto ErrorExit;
   1053             }
   1054         }
   1055 
   1056         if (Index >= Base)
   1057         {
   1058             goto ErrorExit;
   1059         }
   1060 
   1061         /* Check to see if value is out of range: */
   1062 
   1063         if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) /
   1064                             (UINT64) Base))
   1065         {
   1066             goto ErrorExit;
   1067         }
   1068         else
   1069         {
   1070             ReturnValue *= Base;
   1071             ReturnValue += Index;
   1072         }
   1073 
   1074         ++String;
   1075     }
   1076 
   1077 
   1078     /* If a minus sign was present, then "the conversion is negated": */
   1079 
   1080     if (Sign == NEGATIVE)
   1081     {
   1082         ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1;
   1083     }
   1084 
   1085     *RetInteger = ReturnValue;
   1086     return (Status);
   1087 
   1088 
   1089 ErrorExit:
   1090     switch (Base)
   1091     {
   1092     case 8:
   1093 
   1094         Status = AE_BAD_OCTAL_CONSTANT;
   1095         break;
   1096 
   1097     case 10:
   1098 
   1099         Status = AE_BAD_DECIMAL_CONSTANT;
   1100         break;
   1101 
   1102     case 16:
   1103 
   1104         Status = AE_BAD_HEX_CONSTANT;
   1105         break;
   1106 
   1107     default:
   1108 
   1109         /* Base validated above */
   1110 
   1111         break;
   1112     }
   1113 
   1114     return (Status);
   1115 }
   1116