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