Home | History | Annotate | Line # | Download | only in compiler
asltree.c revision 1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: asltree - parse tree management
      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 "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acapps.h"
     47 #include <time.h>
     48 
     49 #define _COMPONENT          ACPI_COMPILER
     50         ACPI_MODULE_NAME    ("asltree")
     51 
     52 /* Local prototypes */
     53 
     54 static ACPI_PARSE_OBJECT *
     55 TrGetNextNode (
     56     void);
     57 
     58 
     59 /*******************************************************************************
     60  *
     61  * FUNCTION:    TrSetParent
     62  *
     63  * PARAMETERS:  Op                  - To be set to new parent
     64  *              ParentOp            - The parent
     65  *
     66  * RETURN:      None, sets Op parent directly
     67  *
     68  * DESCRIPTION: Change the parent of a parse op.
     69  *
     70  ******************************************************************************/
     71 
     72 void
     73 TrSetParent (
     74     ACPI_PARSE_OBJECT       *Op,
     75     ACPI_PARSE_OBJECT       *ParentOp)
     76 {
     77 
     78     Op->Asl.Parent = ParentOp;
     79 }
     80 
     81 
     82 /*******************************************************************************
     83  *
     84  * FUNCTION:    TrGetNextNode
     85  *
     86  * PARAMETERS:  None
     87  *
     88  * RETURN:      New parse node. Aborts on allocation failure
     89  *
     90  * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
     91  *              dynamic memory manager for performance reasons (This has a
     92  *              major impact on the speed of the compiler.)
     93  *
     94  ******************************************************************************/
     95 
     96 static ACPI_PARSE_OBJECT *
     97 TrGetNextNode (
     98     void)
     99 {
    100     ASL_CACHE_INFO          *Cache;
    101 
    102 
    103     if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
    104     {
    105         /* Allocate a new buffer */
    106 
    107         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    108             (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
    109 
    110         /* Link new cache buffer to head of list */
    111 
    112         Cache->Next = Gbl_ParseOpCacheList;
    113         Gbl_ParseOpCacheList = Cache;
    114 
    115         /* Setup cache management pointers */
    116 
    117         Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
    118         Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
    119     }
    120 
    121     Gbl_ParseOpCount++;
    122     return (Gbl_ParseOpCacheNext++);
    123 }
    124 
    125 
    126 /*******************************************************************************
    127  *
    128  * FUNCTION:    TrAllocateNode
    129  *
    130  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
    131  *
    132  * RETURN:      New parse node. Aborts on allocation failure
    133  *
    134  * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
    135  *
    136  ******************************************************************************/
    137 
    138 ACPI_PARSE_OBJECT *
    139 TrAllocateNode (
    140     UINT32                  ParseOpcode)
    141 {
    142     ACPI_PARSE_OBJECT       *Op;
    143 
    144 
    145     Op = TrGetNextNode ();
    146 
    147     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
    148     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
    149     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
    150     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
    151     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
    152     Op->Asl.Column            = Gbl_CurrentColumn;
    153 
    154     UtSetParseOpName (Op);
    155     return (Op);
    156 }
    157 
    158 
    159 /*******************************************************************************
    160  *
    161  * FUNCTION:    TrReleaseNode
    162  *
    163  * PARAMETERS:  Op            - Op to be released
    164  *
    165  * RETURN:      None
    166  *
    167  * DESCRIPTION: "release" a node. In truth, nothing is done since the node
    168  *              is part of a larger buffer
    169  *
    170  ******************************************************************************/
    171 
    172 void
    173 TrReleaseNode (
    174     ACPI_PARSE_OBJECT       *Op)
    175 {
    176 
    177     return;
    178 }
    179 
    180 
    181 /*******************************************************************************
    182  *
    183  * FUNCTION:    TrSetCurrentFilename
    184  *
    185  * PARAMETERS:  Op                  - An existing parse node
    186  *
    187  * RETURN:      None
    188  *
    189  * DESCRIPTION: Save the include file filename. Used for debug output only.
    190  *
    191  ******************************************************************************/
    192 
    193 void
    194 TrSetCurrentFilename (
    195     ACPI_PARSE_OBJECT       *Op)
    196 {
    197     Op->Asl.Filename = Gbl_PreviousIncludeFilename;
    198 }
    199 
    200 
    201 /*******************************************************************************
    202  *
    203  * FUNCTION:    TrUpdateNode
    204  *
    205  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    206  *              Op                  - An existing parse node
    207  *
    208  * RETURN:      The updated node
    209  *
    210  * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
    211  *              change an opcode to DEFAULT_ARG so that the node is ignored
    212  *              during the code generation. Also used to set generic integers
    213  *              to a specific size (8, 16, 32, or 64 bits)
    214  *
    215  ******************************************************************************/
    216 
    217 ACPI_PARSE_OBJECT *
    218 TrUpdateNode (
    219     UINT32                  ParseOpcode,
    220     ACPI_PARSE_OBJECT       *Op)
    221 {
    222 
    223     if (!Op)
    224     {
    225         return (NULL);
    226     }
    227 
    228     DbgPrint (ASL_PARSE_OUTPUT,
    229         "\nUpdateNode: Old - %s, New - %s\n",
    230         UtGetOpName (Op->Asl.ParseOpcode),
    231         UtGetOpName (ParseOpcode));
    232 
    233     /* Assign new opcode and name */
    234 
    235     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
    236     {
    237         switch (ParseOpcode)
    238         {
    239         case PARSEOP_BYTECONST:
    240 
    241             Op->Asl.Value.Integer = ACPI_UINT8_MAX;
    242             break;
    243 
    244         case PARSEOP_WORDCONST:
    245 
    246             Op->Asl.Value.Integer = ACPI_UINT16_MAX;
    247             break;
    248 
    249         case PARSEOP_DWORDCONST:
    250 
    251             Op->Asl.Value.Integer = ACPI_UINT32_MAX;
    252             break;
    253 
    254         /* Don't need to do the QWORD case */
    255 
    256         default:
    257 
    258             /* Don't care about others */
    259             break;
    260         }
    261     }
    262 
    263     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
    264     UtSetParseOpName (Op);
    265 
    266     /*
    267      * For the BYTE, WORD, and DWORD constants, make sure that the integer
    268      * that was passed in will actually fit into the data type
    269      */
    270     switch (ParseOpcode)
    271     {
    272     case PARSEOP_BYTECONST:
    273 
    274         UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
    275         Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
    276         break;
    277 
    278     case PARSEOP_WORDCONST:
    279 
    280         UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
    281         Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
    282         break;
    283 
    284     case PARSEOP_DWORDCONST:
    285 
    286         UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
    287         Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
    288         break;
    289 
    290     default:
    291 
    292         /* Don't care about others, don't need to check QWORD */
    293 
    294         break;
    295     }
    296 
    297     return (Op);
    298 }
    299 
    300 
    301 /*******************************************************************************
    302  *
    303  * FUNCTION:    TrPrintNodeCompileFlags
    304  *
    305  * PARAMETERS:  Flags               - Flags word to be decoded
    306  *
    307  * RETURN:      None
    308  *
    309  * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
    310  *
    311  ******************************************************************************/
    312 
    313 void
    314 TrPrintNodeCompileFlags (
    315     UINT32                  Flags)
    316 {
    317     UINT32                  i;
    318     UINT32                  FlagBit = 1;
    319     char                    *FlagName = NULL;
    320 
    321 
    322     for (i = 0; i < 32; i++)
    323     {
    324         switch (Flags & FlagBit)
    325         {
    326         case NODE_VISITED:
    327 
    328             FlagName = "NODE_VISITED";
    329             break;
    330 
    331         case NODE_AML_PACKAGE:
    332 
    333             FlagName = "NODE_AML_PACKAGE";
    334             break;
    335 
    336         case NODE_IS_TARGET:
    337 
    338             FlagName = "NODE_IS_TARGET";
    339             break;
    340 
    341         case NODE_IS_RESOURCE_DESC:
    342 
    343             FlagName = "NODE_IS_RESOURCE_DESC";
    344             break;
    345 
    346         case NODE_IS_RESOURCE_FIELD:
    347 
    348             FlagName = "NODE_IS_RESOURCE_FIELD";
    349             break;
    350 
    351         case NODE_HAS_NO_EXIT:
    352 
    353             FlagName = "NODE_HAS_NO_EXIT";
    354             break;
    355 
    356         case NODE_IF_HAS_NO_EXIT:
    357 
    358             FlagName = "NODE_IF_HAS_NO_EXIT";
    359             break;
    360 
    361         case NODE_NAME_INTERNALIZED:
    362 
    363             FlagName = "NODE_NAME_INTERNALIZED";
    364             break;
    365 
    366         case NODE_METHOD_NO_RETVAL:
    367 
    368             FlagName = "NODE_METHOD_NO_RETVAL";
    369             break;
    370 
    371         case NODE_METHOD_SOME_NO_RETVAL:
    372 
    373             FlagName = "NODE_METHOD_SOME_NO_RETVAL";
    374             break;
    375 
    376         case NODE_RESULT_NOT_USED:
    377 
    378             FlagName = "NODE_RESULT_NOT_USED";
    379             break;
    380 
    381         case NODE_METHOD_TYPED:
    382 
    383             FlagName = "NODE_METHOD_TYPED";
    384             break;
    385 
    386         case NODE_COULD_NOT_REDUCE:
    387 
    388             FlagName = "NODE_COULD_NOT_REDUCE";
    389             break;
    390 
    391         case NODE_COMPILE_TIME_CONST:
    392 
    393             FlagName = "NODE_COMPILE_TIME_CONST";
    394             break;
    395 
    396         case NODE_IS_TERM_ARG:
    397 
    398             FlagName = "NODE_IS_TERM_ARG";
    399             break;
    400 
    401         case NODE_WAS_ONES_OP:
    402 
    403             FlagName = "NODE_WAS_ONES_OP";
    404             break;
    405 
    406         case NODE_IS_NAME_DECLARATION:
    407 
    408             FlagName = "NODE_IS_NAME_DECLARATION";
    409             break;
    410 
    411         case NODE_COMPILER_EMITTED:
    412 
    413             FlagName = "NODE_COMPILER_EMITTED";
    414             break;
    415 
    416         case NODE_IS_DUPLICATE:
    417 
    418             FlagName = "NODE_IS_DUPLICATE";
    419             break;
    420 
    421         case NODE_IS_RESOURCE_DATA:
    422 
    423             FlagName = "NODE_IS_RESOURCE_DATA";
    424             break;
    425 
    426         case NODE_IS_NULL_RETURN:
    427 
    428             FlagName = "NODE_IS_NULL_RETURN";
    429             break;
    430 
    431         default:
    432             break;
    433         }
    434 
    435         if (FlagName)
    436         {
    437             DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
    438             FlagName = NULL;
    439         }
    440 
    441         FlagBit <<= 1;
    442     }
    443 }
    444 
    445 
    446 /*******************************************************************************
    447  *
    448  * FUNCTION:    TrSetNodeFlags
    449  *
    450  * PARAMETERS:  Op                  - An existing parse node
    451  *              Flags               - New flags word
    452  *
    453  * RETURN:      The updated parser op
    454  *
    455  * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
    456  *
    457  ******************************************************************************/
    458 
    459 ACPI_PARSE_OBJECT *
    460 TrSetNodeFlags (
    461     ACPI_PARSE_OBJECT       *Op,
    462     UINT32                  Flags)
    463 {
    464 
    465     if (!Op)
    466     {
    467         return (NULL);
    468     }
    469 
    470     DbgPrint (ASL_PARSE_OUTPUT,
    471         "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
    472 
    473     TrPrintNodeCompileFlags (Flags);
    474     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    475 
    476     Op->Asl.CompileFlags |= Flags;
    477     return (Op);
    478 }
    479 
    480 
    481 /*******************************************************************************
    482  *
    483  * FUNCTION:    TrSetNodeAmlLength
    484  *
    485  * PARAMETERS:  Op                  - An existing parse node
    486  *              Length              - AML Length
    487  *
    488  * RETURN:      The updated parser op
    489  *
    490  * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
    491  *              the presence of a node that must be reduced to a fixed length
    492  *              constant.
    493  *
    494  ******************************************************************************/
    495 
    496 ACPI_PARSE_OBJECT *
    497 TrSetNodeAmlLength (
    498     ACPI_PARSE_OBJECT       *Op,
    499     UINT32                  Length)
    500 {
    501 
    502     DbgPrint (ASL_PARSE_OUTPUT,
    503         "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
    504 
    505     if (!Op)
    506     {
    507         return (NULL);
    508     }
    509 
    510     Op->Asl.AmlLength = Length;
    511     return (Op);
    512 }
    513 
    514 
    515 /*******************************************************************************
    516  *
    517  * FUNCTION:    TrSetEndLineNumber
    518  *
    519  * PARAMETERS:  Op                - An existing parse node
    520  *
    521  * RETURN:      None.
    522  *
    523  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
    524  *              parse node to the current line numbers.
    525  *
    526  ******************************************************************************/
    527 
    528 void
    529 TrSetEndLineNumber (
    530     ACPI_PARSE_OBJECT       *Op)
    531 {
    532 
    533     /* If the end line # is already set, just return */
    534 
    535     if (Op->Asl.EndLine)
    536     {
    537         return;
    538     }
    539 
    540     Op->Asl.EndLine = Gbl_CurrentLineNumber;
    541     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
    542 }
    543 
    544 
    545 /*******************************************************************************
    546  *
    547  * FUNCTION:    TrCreateAssignmentNode
    548  *
    549  * PARAMETERS:  Target              - Assignment target
    550  *              Source              - Assignment source
    551  *
    552  * RETURN:      Pointer to the new node. Aborts on allocation failure
    553  *
    554  * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
    555  *              tree if possible to utilize the last argument of the math
    556  *              operators which is a target operand -- thus saving invocation
    557  *              of and additional Store() operator. An optimization.
    558  *
    559  ******************************************************************************/
    560 
    561 ACPI_PARSE_OBJECT *
    562 TrCreateAssignmentNode (
    563     ACPI_PARSE_OBJECT       *Target,
    564     ACPI_PARSE_OBJECT       *Source)
    565 {
    566     ACPI_PARSE_OBJECT       *TargetOp;
    567     ACPI_PARSE_OBJECT       *SourceOp1;
    568     ACPI_PARSE_OBJECT       *SourceOp2;
    569     ACPI_PARSE_OBJECT       *Operator;
    570 
    571 
    572     DbgPrint (ASL_PARSE_OUTPUT,
    573         "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
    574         Source->Asl.LineNumber, Source->Asl.EndLine,
    575         UtGetOpName (Source->Asl.ParseOpcode),
    576         UtGetOpName (Target->Asl.ParseOpcode));
    577 
    578     TrSetNodeFlags (Target, NODE_IS_TARGET);
    579 
    580     switch (Source->Asl.ParseOpcode)
    581     {
    582     /*
    583      * Only these operators can be optimized because they have
    584      * a target operand
    585      */
    586     case PARSEOP_ADD:
    587     case PARSEOP_AND:
    588     case PARSEOP_DIVIDE:
    589     case PARSEOP_INDEX:
    590     case PARSEOP_MOD:
    591     case PARSEOP_MULTIPLY:
    592     case PARSEOP_NOT:
    593     case PARSEOP_OR:
    594     case PARSEOP_SHIFTLEFT:
    595     case PARSEOP_SHIFTRIGHT:
    596     case PARSEOP_SUBTRACT:
    597     case PARSEOP_XOR:
    598 
    599         break;
    600 
    601     /* Otherwise, just create a normal Store operator */
    602 
    603     default:
    604 
    605         goto CannotOptimize;
    606     }
    607 
    608     /*
    609      * Transform the parse tree such that the target is moved to the
    610      * last operand of the operator
    611      */
    612     SourceOp1 = Source->Asl.Child;
    613     SourceOp2 = SourceOp1->Asl.Next;
    614 
    615     /* NOT only has one operand, but has a target */
    616 
    617     if (Source->Asl.ParseOpcode == PARSEOP_NOT)
    618     {
    619         SourceOp2 = SourceOp1;
    620     }
    621 
    622     /* DIVIDE has an extra target operand (remainder) */
    623 
    624     if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
    625     {
    626         SourceOp2 = SourceOp2->Asl.Next;
    627     }
    628 
    629     TargetOp = SourceOp2->Asl.Next;
    630 
    631     /*
    632      * Can't perform this optimization if there already is a target
    633      * for the operator (ZERO is a "no target" placeholder).
    634      */
    635     if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
    636     {
    637         goto CannotOptimize;
    638     }
    639 
    640     /* Link in the target as the final operand */
    641 
    642     SourceOp2->Asl.Next = Target;
    643     Target->Asl.Parent = Source;
    644 
    645     return (Source);
    646 
    647 
    648 CannotOptimize:
    649 
    650     Operator = TrAllocateNode (PARSEOP_STORE);
    651     TrLinkChildren (Operator, 2, Source, Target);
    652 
    653     /* Set the appropriate line numbers for the new node */
    654 
    655     Operator->Asl.LineNumber        = Target->Asl.LineNumber;
    656     Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
    657     Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
    658     Operator->Asl.Column            = Target->Asl.Column;
    659 
    660     return (Operator);
    661 }
    662 
    663 
    664 /*******************************************************************************
    665  *
    666  * FUNCTION:    TrCreateLeafNode
    667  *
    668  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    669  *
    670  * RETURN:      Pointer to the new node. Aborts on allocation failure
    671  *
    672  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
    673  *              assigned to the node)
    674  *
    675  ******************************************************************************/
    676 
    677 ACPI_PARSE_OBJECT *
    678 TrCreateLeafNode (
    679     UINT32                  ParseOpcode)
    680 {
    681     ACPI_PARSE_OBJECT       *Op;
    682 
    683 
    684     Op = TrAllocateNode (ParseOpcode);
    685 
    686     DbgPrint (ASL_PARSE_OUTPUT,
    687         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
    688         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
    689 
    690     return (Op);
    691 }
    692 
    693 
    694 /*******************************************************************************
    695  *
    696  * FUNCTION:    TrCreateNullTarget
    697  *
    698  * PARAMETERS:  None
    699  *
    700  * RETURN:      Pointer to the new node. Aborts on allocation failure
    701  *
    702  * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
    703  *              specification to be a zero AML opcode, and indicates that
    704  *              no target has been specified for the parent operation
    705  *
    706  ******************************************************************************/
    707 
    708 ACPI_PARSE_OBJECT *
    709 TrCreateNullTarget (
    710     void)
    711 {
    712     ACPI_PARSE_OBJECT       *Op;
    713 
    714 
    715     Op = TrAllocateNode (PARSEOP_ZERO);
    716     Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
    717 
    718     DbgPrint (ASL_PARSE_OUTPUT,
    719         "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
    720         Op->Asl.LineNumber, Op->Asl.Column, Op,
    721         UtGetOpName (Op->Asl.ParseOpcode));
    722 
    723     return (Op);
    724 }
    725 
    726 
    727 /*******************************************************************************
    728  *
    729  * FUNCTION:    TrCreateConstantLeafNode
    730  *
    731  * PARAMETERS:  ParseOpcode         - The constant opcode
    732  *
    733  * RETURN:      Pointer to the new node. Aborts on allocation failure
    734  *
    735  * DESCRIPTION: Create a leaf node (no children or peers) for one of the
    736  *              special constants - __LINE__, __FILE__, and __DATE__.
    737  *
    738  * Note: An implemenation of __FUNC__ cannot happen here because we don't
    739  * have a full parse tree at this time and cannot find the parent control
    740  * method. If it is ever needed, __FUNC__ must be implemented later, after
    741  * the parse tree has been fully constructed.
    742  *
    743  ******************************************************************************/
    744 
    745 ACPI_PARSE_OBJECT *
    746 TrCreateConstantLeafNode (
    747     UINT32                  ParseOpcode)
    748 {
    749     ACPI_PARSE_OBJECT       *Op = NULL;
    750     time_t                  CurrentTime;
    751     char                    *StaticTimeString;
    752     char                    *TimeString;
    753     char                    *Filename;
    754 
    755 
    756     switch (ParseOpcode)
    757     {
    758     case PARSEOP___LINE__:
    759 
    760         Op = TrAllocateNode (PARSEOP_INTEGER);
    761         Op->Asl.Value.Integer = Op->Asl.LineNumber;
    762         break;
    763 
    764     case PARSEOP___PATH__:
    765 
    766         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    767 
    768         /* Op.Asl.Filename contains the full pathname to the file */
    769 
    770         Op->Asl.Value.String = Op->Asl.Filename;
    771         break;
    772 
    773     case PARSEOP___FILE__:
    774 
    775         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    776 
    777         /* Get the simple filename from the full path */
    778 
    779         FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
    780         Op->Asl.Value.String = Filename;
    781         break;
    782 
    783     case PARSEOP___DATE__:
    784 
    785         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    786 
    787         /* Get a copy of the current time */
    788 
    789         CurrentTime = time (NULL);
    790         StaticTimeString = ctime (&CurrentTime);
    791         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
    792         strcpy (TimeString, StaticTimeString);
    793 
    794         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
    795         Op->Asl.Value.String = TimeString;
    796         break;
    797 
    798     default: /* This would be an internal error */
    799 
    800         return (NULL);
    801     }
    802 
    803     DbgPrint (ASL_PARSE_OUTPUT,
    804         "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  "
    805         "Op %s  Value %8.8X%8.8X  \n",
    806         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
    807         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
    808     return (Op);
    809 }
    810 
    811 
    812 /*******************************************************************************
    813  *
    814  * FUNCTION:    TrCreateTargetOperand
    815  *
    816  * PARAMETERS:  OriginalOp          - Op to be copied
    817  *
    818  * RETURN:      Pointer to the new node. Aborts on allocation failure
    819  *
    820  * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
    821  *              expressions where the target is the same as one of the
    822  *              operands. A new node and subtree must be created from the
    823  *              original so that the parse tree can be linked properly.
    824  *
    825  * NOTE:        This code is specific to target operands that are the last
    826  *              operand in an ASL/AML operator. Meaning that the top-level
    827  *              parse Op in a possible subtree has a NULL Next pointer.
    828  *              This simplifies the recursion.
    829  *
    830  *              Subtree example:
    831  *                  DeRefOf (Local1) += 32
    832  *
    833  *              This gets converted to:
    834  *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
    835  *
    836  *              Each DeRefOf has a single child, Local1. Even more complex
    837  *              subtrees can be created via the Index and DeRefOf operators.
    838  *
    839  ******************************************************************************/
    840 
    841 ACPI_PARSE_OBJECT *
    842 TrCreateTargetOperand (
    843     ACPI_PARSE_OBJECT       *OriginalOp,
    844     ACPI_PARSE_OBJECT       *ParentOp)
    845 {
    846     ACPI_PARSE_OBJECT       *Op;
    847 
    848 
    849     if (!OriginalOp)
    850     {
    851         return (NULL);
    852     }
    853 
    854     Op = TrGetNextNode ();
    855 
    856     /* Copy the pertinent values (omit link pointer fields) */
    857 
    858     Op->Asl.Value               = OriginalOp->Asl.Value;
    859     Op->Asl.Filename            = OriginalOp->Asl.Filename;
    860     Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
    861     Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
    862     Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
    863     Op->Asl.Column              = OriginalOp->Asl.Column;
    864     Op->Asl.Flags               = OriginalOp->Asl.Flags;
    865     Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
    866     Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
    867     Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
    868     Op->Asl.Parent              = ParentOp;
    869     UtSetParseOpName (Op);
    870 
    871     /* Copy a possible subtree below this node */
    872 
    873     if (OriginalOp->Asl.Child)
    874     {
    875         Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
    876     }
    877 
    878     if (OriginalOp->Asl.Next) /* Null for top-level node */
    879     {
    880         Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
    881     }
    882 
    883     return (Op);
    884 }
    885 
    886 
    887 /*******************************************************************************
    888  *
    889  * FUNCTION:    TrCreateValuedLeafNode
    890  *
    891  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    892  *              Value               - Value to be assigned to the node
    893  *
    894  * RETURN:      Pointer to the new node. Aborts on allocation failure
    895  *
    896  * DESCRIPTION: Create a leaf node (no children or peers) with a value
    897  *              assigned to it
    898  *
    899  ******************************************************************************/
    900 
    901 ACPI_PARSE_OBJECT *
    902 TrCreateValuedLeafNode (
    903     UINT32                  ParseOpcode,
    904     UINT64                  Value)
    905 {
    906     ACPI_PARSE_OBJECT       *Op;
    907 
    908 
    909     Op = TrAllocateNode (ParseOpcode);
    910 
    911     DbgPrint (ASL_PARSE_OUTPUT,
    912         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  "
    913         "Op %s  Value %8.8X%8.8X  ",
    914         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
    915         ACPI_FORMAT_UINT64 (Value));
    916     Op->Asl.Value.Integer = Value;
    917 
    918     switch (ParseOpcode)
    919     {
    920     case PARSEOP_STRING_LITERAL:
    921 
    922         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
    923         break;
    924 
    925     case PARSEOP_NAMESEG:
    926 
    927         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
    928         break;
    929 
    930     case PARSEOP_NAMESTRING:
    931 
    932         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
    933         break;
    934 
    935     case PARSEOP_EISAID:
    936 
    937         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
    938         break;
    939 
    940     case PARSEOP_METHOD:
    941 
    942         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
    943         break;
    944 
    945     case PARSEOP_INTEGER:
    946 
    947         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
    948             ACPI_FORMAT_UINT64 (Value));
    949         break;
    950 
    951     default:
    952 
    953         break;
    954     }
    955 
    956     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    957     return (Op);
    958 }
    959 
    960 
    961 /*******************************************************************************
    962  *
    963  * FUNCTION:    TrCreateNode
    964  *
    965  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
    966  *              NumChildren         - Number of children to follow
    967  *              ...                 - A list of child nodes to link to the new
    968  *                                    node. NumChildren long.
    969  *
    970  * RETURN:      Pointer to the new node. Aborts on allocation failure
    971  *
    972  * DESCRIPTION: Create a new parse node and link together a list of child
    973  *              nodes underneath the new node.
    974  *
    975  ******************************************************************************/
    976 
    977 ACPI_PARSE_OBJECT *
    978 TrCreateNode (
    979     UINT32                  ParseOpcode,
    980     UINT32                  NumChildren,
    981     ...)
    982 {
    983     ACPI_PARSE_OBJECT       *Op;
    984     ACPI_PARSE_OBJECT       *Child;
    985     ACPI_PARSE_OBJECT       *PrevChild;
    986     va_list                 ap;
    987     UINT32                  i;
    988     BOOLEAN                 FirstChild;
    989 
    990 
    991     va_start (ap, NumChildren);
    992 
    993     /* Allocate one new node */
    994 
    995     Op = TrAllocateNode (ParseOpcode);
    996 
    997     DbgPrint (ASL_PARSE_OUTPUT,
    998         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
    999         Op->Asl.LineNumber, Op->Asl.Column, Op,
   1000         NumChildren, UtGetOpName(ParseOpcode));
   1001 
   1002     /* Some extra debug output based on the parse opcode */
   1003 
   1004     switch (ParseOpcode)
   1005     {
   1006     case PARSEOP_ASL_CODE:
   1007 
   1008         Gbl_ParseTreeRoot = Op;
   1009         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1010         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
   1011         break;
   1012 
   1013     case PARSEOP_DEFINITION_BLOCK:
   1014 
   1015         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
   1016         break;
   1017 
   1018     case PARSEOP_OPERATIONREGION:
   1019 
   1020         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
   1021         break;
   1022 
   1023     case PARSEOP_OR:
   1024 
   1025         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
   1026         break;
   1027 
   1028     default:
   1029 
   1030         /* Nothing to do for other opcodes */
   1031 
   1032         break;
   1033     }
   1034 
   1035     /* Link the new node to its children */
   1036 
   1037     PrevChild = NULL;
   1038     FirstChild = TRUE;
   1039     for (i = 0; i < NumChildren; i++)
   1040     {
   1041         /* Get the next child */
   1042 
   1043         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
   1044         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
   1045 
   1046         /*
   1047          * If child is NULL, this means that an optional argument
   1048          * was omitted. We must create a placeholder with a special
   1049          * opcode (DEFAULT_ARG) so that the code generator will know
   1050          * that it must emit the correct default for this argument
   1051          */
   1052         if (!Child)
   1053         {
   1054             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
   1055         }
   1056 
   1057         /* Link first child to parent */
   1058 
   1059         if (FirstChild)
   1060         {
   1061             FirstChild = FALSE;
   1062             Op->Asl.Child = Child;
   1063         }
   1064 
   1065         /* Point all children to parent */
   1066 
   1067         Child->Asl.Parent = Op;
   1068 
   1069         /* Link children in a peer list */
   1070 
   1071         if (PrevChild)
   1072         {
   1073             PrevChild->Asl.Next = Child;
   1074         };
   1075 
   1076         /*
   1077          * This child might be a list, point all nodes in the list
   1078          * to the same parent
   1079          */
   1080         while (Child->Asl.Next)
   1081         {
   1082             Child = Child->Asl.Next;
   1083             Child->Asl.Parent = Op;
   1084         }
   1085 
   1086         PrevChild = Child;
   1087     }
   1088     va_end(ap);
   1089 
   1090     DbgPrint (ASL_PARSE_OUTPUT, "\n");
   1091     return (Op);
   1092 }
   1093 
   1094 
   1095 /*******************************************************************************
   1096  *
   1097  * FUNCTION:    TrLinkChildren
   1098  *
   1099  * PARAMETERS:  Op                - An existing parse node
   1100  *              NumChildren         - Number of children to follow
   1101  *              ...                 - A list of child nodes to link to the new
   1102  *                                    node. NumChildren long.
   1103  *
   1104  * RETURN:      The updated (linked) node
   1105  *
   1106  * DESCRIPTION: Link a group of nodes to an existing parse node
   1107  *
   1108  ******************************************************************************/
   1109 
   1110 ACPI_PARSE_OBJECT *
   1111 TrLinkChildren (
   1112     ACPI_PARSE_OBJECT       *Op,
   1113     UINT32                  NumChildren,
   1114     ...)
   1115 {
   1116     ACPI_PARSE_OBJECT       *Child;
   1117     ACPI_PARSE_OBJECT       *PrevChild;
   1118     va_list                 ap;
   1119     UINT32                  i;
   1120     BOOLEAN                 FirstChild;
   1121 
   1122 
   1123     va_start (ap, NumChildren);
   1124 
   1125 
   1126     TrSetEndLineNumber (Op);
   1127 
   1128     DbgPrint (ASL_PARSE_OUTPUT,
   1129         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
   1130         Op->Asl.LineNumber, Op->Asl.EndLine,
   1131         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
   1132 
   1133     switch (Op->Asl.ParseOpcode)
   1134     {
   1135     case PARSEOP_ASL_CODE:
   1136 
   1137         Gbl_ParseTreeRoot = Op;
   1138         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1139         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
   1140         break;
   1141 
   1142     case PARSEOP_DEFINITION_BLOCK:
   1143 
   1144         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
   1145         break;
   1146 
   1147     case PARSEOP_OPERATIONREGION:
   1148 
   1149         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
   1150         break;
   1151 
   1152     case PARSEOP_OR:
   1153 
   1154         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
   1155         break;
   1156 
   1157     default:
   1158 
   1159         /* Nothing to do for other opcodes */
   1160 
   1161         break;
   1162     }
   1163 
   1164     /* Link the new node to it's children */
   1165 
   1166     PrevChild = NULL;
   1167     FirstChild = TRUE;
   1168     for (i = 0; i < NumChildren; i++)
   1169     {
   1170         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
   1171 
   1172         if ((Child == PrevChild) && (Child != NULL))
   1173         {
   1174             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
   1175                 "Child node list invalid");
   1176             va_end(ap);
   1177             return (Op);
   1178         }
   1179 
   1180         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
   1181 
   1182         /*
   1183          * If child is NULL, this means that an optional argument
   1184          * was omitted. We must create a placeholder with a special
   1185          * opcode (DEFAULT_ARG) so that the code generator will know
   1186          * that it must emit the correct default for this argument
   1187          */
   1188         if (!Child)
   1189         {
   1190             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
   1191         }
   1192 
   1193         /* Link first child to parent */
   1194 
   1195         if (FirstChild)
   1196         {
   1197             FirstChild = FALSE;
   1198             Op->Asl.Child = Child;
   1199         }
   1200 
   1201         /* Point all children to parent */
   1202 
   1203         Child->Asl.Parent = Op;
   1204 
   1205         /* Link children in a peer list */
   1206 
   1207         if (PrevChild)
   1208         {
   1209             PrevChild->Asl.Next = Child;
   1210         };
   1211 
   1212         /*
   1213          * This child might be a list, point all nodes in the list
   1214          * to the same parent
   1215          */
   1216         while (Child->Asl.Next)
   1217         {
   1218             Child = Child->Asl.Next;
   1219             Child->Asl.Parent = Op;
   1220         }
   1221 
   1222         PrevChild = Child;
   1223     }
   1224 
   1225     va_end(ap);
   1226     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
   1227     return (Op);
   1228 }
   1229 
   1230 
   1231 /*******************************************************************************
   1232  *
   1233  * FUNCTION:    TrLinkPeerNode
   1234  *
   1235  * PARAMETERS:  Op1           - First peer
   1236  *              Op2           - Second peer
   1237  *
   1238  * RETURN:      Op1 or the non-null node.
   1239  *
   1240  * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
   1241  *
   1242  ******************************************************************************/
   1243 
   1244 ACPI_PARSE_OBJECT *
   1245 TrLinkPeerNode (
   1246     ACPI_PARSE_OBJECT       *Op1,
   1247     ACPI_PARSE_OBJECT       *Op2)
   1248 {
   1249     ACPI_PARSE_OBJECT       *Next;
   1250 
   1251 
   1252     DbgPrint (ASL_PARSE_OUTPUT,
   1253         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
   1254         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
   1255         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
   1256 
   1257 
   1258     if ((!Op1) && (!Op2))
   1259     {
   1260         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
   1261         return (Op1);
   1262     }
   1263 
   1264     /* If one of the nodes is null, just return the non-null node */
   1265 
   1266     if (!Op2)
   1267     {
   1268         return (Op1);
   1269     }
   1270 
   1271     if (!Op1)
   1272     {
   1273         return (Op2);
   1274     }
   1275 
   1276     if (Op1 == Op2)
   1277     {
   1278         DbgPrint (ASL_DEBUG_OUTPUT,
   1279             "\n************* Internal error, linking node to itself %p\n",
   1280             Op1);
   1281         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
   1282             "Linking node to itself");
   1283         return (Op1);
   1284     }
   1285 
   1286     Op1->Asl.Parent = Op2->Asl.Parent;
   1287 
   1288     /*
   1289      * Op 1 may already have a peer list (such as an IF/ELSE pair),
   1290      * so we must walk to the end of the list and attach the new
   1291      * peer at the end
   1292      */
   1293     Next = Op1;
   1294     while (Next->Asl.Next)
   1295     {
   1296         Next = Next->Asl.Next;
   1297     }
   1298 
   1299     Next->Asl.Next = Op2;
   1300     return (Op1);
   1301 }
   1302 
   1303 
   1304 /*******************************************************************************
   1305  *
   1306  * FUNCTION:    TrLinkPeerNodes
   1307  *
   1308  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
   1309  *              ...                 - A list of nodes to link together as peers
   1310  *
   1311  * RETURN:      The first node in the list (head of the peer list)
   1312  *
   1313  * DESCRIPTION: Link together an arbitrary number of peer nodes.
   1314  *
   1315  ******************************************************************************/
   1316 
   1317 ACPI_PARSE_OBJECT *
   1318 TrLinkPeerNodes (
   1319     UINT32                  NumPeers,
   1320     ...)
   1321 {
   1322     ACPI_PARSE_OBJECT       *This;
   1323     ACPI_PARSE_OBJECT       *Next;
   1324     va_list                 ap;
   1325     UINT32                  i;
   1326     ACPI_PARSE_OBJECT       *Start;
   1327 
   1328 
   1329     DbgPrint (ASL_PARSE_OUTPUT,
   1330         "\nLinkPeerNodes: (%u) ", NumPeers);
   1331 
   1332     va_start (ap, NumPeers);
   1333     This = va_arg (ap, ACPI_PARSE_OBJECT *);
   1334     Start = This;
   1335 
   1336     /*
   1337      * Link all peers
   1338      */
   1339     for (i = 0; i < (NumPeers -1); i++)
   1340     {
   1341         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
   1342 
   1343         while (This->Asl.Next)
   1344         {
   1345             This = This->Asl.Next;
   1346         }
   1347 
   1348         /* Get another peer node */
   1349 
   1350         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
   1351         if (!Next)
   1352         {
   1353             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
   1354         }
   1355 
   1356         /* link new node to the current node */
   1357 
   1358         This->Asl.Next = Next;
   1359         This = Next;
   1360     }
   1361     va_end (ap);
   1362 
   1363     DbgPrint (ASL_PARSE_OUTPUT,"\n");
   1364     return (Start);
   1365 }
   1366 
   1367 
   1368 /*******************************************************************************
   1369  *
   1370  * FUNCTION:    TrLinkChildNode
   1371  *
   1372  * PARAMETERS:  Op1           - Parent node
   1373  *              Op2           - Op to become a child
   1374  *
   1375  * RETURN:      The parent node
   1376  *
   1377  * DESCRIPTION: Link two nodes together as a parent and child
   1378  *
   1379  ******************************************************************************/
   1380 
   1381 ACPI_PARSE_OBJECT *
   1382 TrLinkChildNode (
   1383     ACPI_PARSE_OBJECT       *Op1,
   1384     ACPI_PARSE_OBJECT       *Op2)
   1385 {
   1386     ACPI_PARSE_OBJECT       *Next;
   1387 
   1388 
   1389     DbgPrint (ASL_PARSE_OUTPUT,
   1390         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
   1391         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
   1392         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
   1393 
   1394     if (!Op1 || !Op2)
   1395     {
   1396         return (Op1);
   1397     }
   1398 
   1399     Op1->Asl.Child = Op2;
   1400 
   1401     /* Set the child and all peers of the child to point to the parent */
   1402 
   1403     Next = Op2;
   1404     while (Next)
   1405     {
   1406         Next->Asl.Parent = Op1;
   1407         Next = Next->Asl.Next;
   1408     }
   1409 
   1410     return (Op1);
   1411 }
   1412 
   1413 
   1414 /*******************************************************************************
   1415  *
   1416  * FUNCTION:    TrWalkParseTree
   1417  *
   1418  * PARAMETERS:  Visitation              - Type of walk
   1419  *              DescendingCallback      - Called during tree descent
   1420  *              AscendingCallback       - Called during tree ascent
   1421  *              Context                 - To be passed to the callbacks
   1422  *
   1423  * RETURN:      Status from callback(s)
   1424  *
   1425  * DESCRIPTION: Walk the entire parse tree.
   1426  *
   1427  ******************************************************************************/
   1428 
   1429 ACPI_STATUS
   1430 TrWalkParseTree (
   1431     ACPI_PARSE_OBJECT       *Op,
   1432     UINT32                  Visitation,
   1433     ASL_WALK_CALLBACK       DescendingCallback,
   1434     ASL_WALK_CALLBACK       AscendingCallback,
   1435     void                    *Context)
   1436 {
   1437     UINT32                  Level;
   1438     BOOLEAN                 NodePreviouslyVisited;
   1439     ACPI_PARSE_OBJECT       *StartOp = Op;
   1440     ACPI_STATUS             Status;
   1441 
   1442 
   1443     if (!Gbl_ParseTreeRoot)
   1444     {
   1445         return (AE_OK);
   1446     }
   1447 
   1448     Level = 0;
   1449     NodePreviouslyVisited = FALSE;
   1450 
   1451     switch (Visitation)
   1452     {
   1453     case ASL_WALK_VISIT_DOWNWARD:
   1454 
   1455         while (Op)
   1456         {
   1457             if (!NodePreviouslyVisited)
   1458             {
   1459                 /* Let the callback process the node. */
   1460 
   1461                 Status = DescendingCallback (Op, Level, Context);
   1462                 if (ACPI_SUCCESS (Status))
   1463                 {
   1464                     /* Visit children first, once */
   1465 
   1466                     if (Op->Asl.Child)
   1467                     {
   1468                         Level++;
   1469                         Op = Op->Asl.Child;
   1470                         continue;
   1471                     }
   1472                 }
   1473                 else if (Status != AE_CTRL_DEPTH)
   1474                 {
   1475                     /* Exit immediately on any error */
   1476 
   1477                     return (Status);
   1478                 }
   1479             }
   1480 
   1481             /* Terminate walk at start op */
   1482 
   1483             if (Op == StartOp)
   1484             {
   1485                 break;
   1486             }
   1487 
   1488             /* No more children, visit peers */
   1489 
   1490             if (Op->Asl.Next)
   1491             {
   1492                 Op = Op->Asl.Next;
   1493                 NodePreviouslyVisited = FALSE;
   1494             }
   1495             else
   1496             {
   1497                 /* No children or peers, re-visit parent */
   1498 
   1499                 if (Level != 0 )
   1500                 {
   1501                     Level--;
   1502                 }
   1503                 Op = Op->Asl.Parent;
   1504                 NodePreviouslyVisited = TRUE;
   1505             }
   1506         }
   1507         break;
   1508 
   1509     case ASL_WALK_VISIT_UPWARD:
   1510 
   1511         while (Op)
   1512         {
   1513             /* Visit leaf node (no children) or parent node on return trip */
   1514 
   1515             if ((!Op->Asl.Child) ||
   1516                 (NodePreviouslyVisited))
   1517             {
   1518                 /* Let the callback process the node. */
   1519 
   1520                 Status = AscendingCallback (Op, Level, Context);
   1521                 if (ACPI_FAILURE (Status))
   1522                 {
   1523                     return (Status);
   1524                 }
   1525             }
   1526             else
   1527             {
   1528                 /* Visit children first, once */
   1529 
   1530                 Level++;
   1531                 Op = Op->Asl.Child;
   1532                 continue;
   1533             }
   1534 
   1535             /* Terminate walk at start op */
   1536 
   1537             if (Op == StartOp)
   1538             {
   1539                 break;
   1540             }
   1541 
   1542             /* No more children, visit peers */
   1543 
   1544             if (Op->Asl.Next)
   1545             {
   1546                 Op = Op->Asl.Next;
   1547                 NodePreviouslyVisited = FALSE;
   1548             }
   1549             else
   1550             {
   1551                 /* No children or peers, re-visit parent */
   1552 
   1553                 if (Level != 0 )
   1554                 {
   1555                     Level--;
   1556                 }
   1557                 Op = Op->Asl.Parent;
   1558                 NodePreviouslyVisited = TRUE;
   1559             }
   1560         }
   1561         break;
   1562 
   1563      case ASL_WALK_VISIT_TWICE:
   1564 
   1565         while (Op)
   1566         {
   1567             if (NodePreviouslyVisited)
   1568             {
   1569                 Status = AscendingCallback (Op, Level, Context);
   1570                 if (ACPI_FAILURE (Status))
   1571                 {
   1572                     return (Status);
   1573                 }
   1574             }
   1575             else
   1576             {
   1577                 /* Let the callback process the node. */
   1578 
   1579                 Status = DescendingCallback (Op, Level, Context);
   1580                 if (ACPI_SUCCESS (Status))
   1581                 {
   1582                     /* Visit children first, once */
   1583 
   1584                     if (Op->Asl.Child)
   1585                     {
   1586                         Level++;
   1587                         Op = Op->Asl.Child;
   1588                         continue;
   1589                     }
   1590                 }
   1591                 else if (Status != AE_CTRL_DEPTH)
   1592                 {
   1593                     /* Exit immediately on any error */
   1594 
   1595                     return (Status);
   1596                 }
   1597             }
   1598 
   1599             /* Terminate walk at start op */
   1600 
   1601             if (Op == StartOp)
   1602             {
   1603                 break;
   1604             }
   1605 
   1606             /* No more children, visit peers */
   1607 
   1608             if (Op->Asl.Next)
   1609             {
   1610                 Op = Op->Asl.Next;
   1611                 NodePreviouslyVisited = FALSE;
   1612             }
   1613             else
   1614             {
   1615                 /* No children or peers, re-visit parent */
   1616 
   1617                 if (Level != 0 )
   1618                 {
   1619                     Level--;
   1620                 }
   1621                 Op = Op->Asl.Parent;
   1622                 NodePreviouslyVisited = TRUE;
   1623             }
   1624         }
   1625         break;
   1626 
   1627     default:
   1628         /* No other types supported */
   1629         break;
   1630     }
   1631 
   1632     /* If we get here, the walk completed with no errors */
   1633 
   1634     return (AE_OK);
   1635 }
   1636