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