Home | History | Annotate | Line # | Download | only in compiler
asltree.c revision 1.1
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: asltree - parse tree management
      5  *
      6  *****************************************************************************/
      7 
      8 /******************************************************************************
      9  *
     10  * 1. Copyright Notice
     11  *
     12  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     13  * All rights reserved.
     14  *
     15  * 2. License
     16  *
     17  * 2.1. This is your license from Intel Corp. under its intellectual property
     18  * rights.  You may have additional license terms from the party that provided
     19  * you this software, covering your right to use that party's intellectual
     20  * property rights.
     21  *
     22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     23  * copy of the source code appearing in this file ("Covered Code") an
     24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     25  * base code distributed originally by Intel ("Original Intel Code") to copy,
     26  * make derivatives, distribute, use and display any portion of the Covered
     27  * Code in any form, with the right to sublicense such rights; and
     28  *
     29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     30  * license (with the right to sublicense), under only those claims of Intel
     31  * patents that are infringed by the Original Intel Code, to make, use, sell,
     32  * offer to sell, and import the Covered Code and derivative works thereof
     33  * solely to the minimum extent necessary to exercise the above copyright
     34  * license, and in no event shall the patent license extend to any additions
     35  * to or modifications of the Original Intel Code.  No other license or right
     36  * is granted directly or by implication, estoppel or otherwise;
     37  *
     38  * The above copyright and patent license is granted only if the following
     39  * conditions are met:
     40  *
     41  * 3. Conditions
     42  *
     43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     44  * Redistribution of source code of any substantial portion of the Covered
     45  * Code or modification with rights to further distribute source must include
     46  * the above Copyright Notice, the above License, this list of Conditions,
     47  * and the following Disclaimer and Export Compliance provision.  In addition,
     48  * Licensee must cause all Covered Code to which Licensee contributes to
     49  * contain a file documenting the changes Licensee made to create that Covered
     50  * Code and the date of any change.  Licensee must include in that file the
     51  * documentation of any changes made by any predecessor Licensee.  Licensee
     52  * must include a prominent statement that the modification is derived,
     53  * directly or indirectly, from Original Intel Code.
     54  *
     55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     56  * Redistribution of source code of any substantial portion of the Covered
     57  * Code or modification without rights to further distribute source must
     58  * include the following Disclaimer and Export Compliance provision in the
     59  * documentation and/or other materials provided with distribution.  In
     60  * addition, Licensee may not authorize further sublicense of source of any
     61  * portion of the Covered Code, and must include terms to the effect that the
     62  * license from Licensee to its licensee is limited to the intellectual
     63  * property embodied in the software Licensee provides to its licensee, and
     64  * not to intellectual property embodied in modifications its licensee may
     65  * make.
     66  *
     67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     68  * substantial portion of the Covered Code or modification must reproduce the
     69  * above Copyright Notice, and the following Disclaimer and Export Compliance
     70  * provision in the documentation and/or other materials provided with the
     71  * distribution.
     72  *
     73  * 3.4. Intel retains all right, title, and interest in and to the Original
     74  * Intel Code.
     75  *
     76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     77  * Intel shall be used in advertising or otherwise to promote the sale, use or
     78  * other dealings in products derived from or relating to the Covered Code
     79  * without prior written authorization from Intel.
     80  *
     81  * 4. Disclaimer and Export Compliance
     82  *
     83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     89  * PARTICULAR PURPOSE.
     90  *
     91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     98  * LIMITED REMEDY.
     99  *
    100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    101  * software or system incorporating such software without first obtaining any
    102  * required license or other approval from the U. S. Department of Commerce or
    103  * any other agency or department of the United States Government.  In the
    104  * event Licensee exports any such software from the United States or
    105  * re-exports any such software from a foreign destination, Licensee shall
    106  * ensure that the distribution and export/re-export of the software is in
    107  * compliance with all laws, regulations, orders, or other restrictions of the
    108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    109  * any of its subsidiaries will export/re-export any technical data, process,
    110  * software, or service, directly or indirectly, to any country for which the
    111  * United States government or any agency thereof requires an export license,
    112  * other governmental approval, or letter of assurance, without first obtaining
    113  * such license, approval or letter.
    114  *
    115  *****************************************************************************/
    116 
    117 
    118 #include "aslcompiler.h"
    119 #include "aslcompiler.y.h"
    120 
    121 #define _COMPONENT          ACPI_COMPILER
    122         ACPI_MODULE_NAME    ("asltree")
    123 
    124 /* Local prototypes */
    125 
    126 static ACPI_PARSE_OBJECT *
    127 TrGetNextNode (
    128     void);
    129 
    130 static char *
    131 TrGetNodeFlagName (
    132     UINT32                  Flags);
    133 
    134 
    135 /*******************************************************************************
    136  *
    137  * FUNCTION:    TrGetNextNode
    138  *
    139  * PARAMETERS:  None
    140  *
    141  * RETURN:      New parse node.  Aborts on allocation failure
    142  *
    143  * DESCRIPTION: Allocate a new parse node for the parse tree.  Bypass the local
    144  *              dynamic memory manager for performance reasons (This has a
    145  *              major impact on the speed of the compiler.)
    146  *
    147  ******************************************************************************/
    148 
    149 static ACPI_PARSE_OBJECT *
    150 TrGetNextNode (
    151     void)
    152 {
    153 
    154     if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast)
    155     {
    156         Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) *
    157                                 ASL_NODE_CACHE_SIZE);
    158         Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE;
    159     }
    160 
    161     return (Gbl_NodeCacheNext++);
    162 }
    163 
    164 
    165 /*******************************************************************************
    166  *
    167  * FUNCTION:    TrAllocateNode
    168  *
    169  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
    170  *
    171  * RETURN:      New parse node.  Aborts on allocation failure
    172  *
    173  * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
    174  *
    175  ******************************************************************************/
    176 
    177 ACPI_PARSE_OBJECT *
    178 TrAllocateNode (
    179     UINT32                  ParseOpcode)
    180 {
    181     ACPI_PARSE_OBJECT       *Op;
    182 
    183 
    184     Op = TrGetNextNode ();
    185 
    186     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
    187     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
    188     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
    189     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
    190     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
    191     Op->Asl.Column            = Gbl_CurrentColumn;
    192 
    193     UtSetParseOpName (Op);
    194     return Op;
    195 }
    196 
    197 
    198 /*******************************************************************************
    199  *
    200  * FUNCTION:    TrReleaseNode
    201  *
    202  * PARAMETERS:  Op            - Op to be released
    203  *
    204  * RETURN:      None
    205  *
    206  * DESCRIPTION: "release" a node.  In truth, nothing is done since the node
    207  *              is part of a larger buffer
    208  *
    209  ******************************************************************************/
    210 
    211 void
    212 TrReleaseNode (
    213     ACPI_PARSE_OBJECT       *Op)
    214 {
    215 
    216     return;
    217 }
    218 
    219 
    220 /*******************************************************************************
    221  *
    222  * FUNCTION:    TrUpdateNode
    223  *
    224  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    225  *              Op                - An existing parse node
    226  *
    227  * RETURN:      The updated node
    228  *
    229  * DESCRIPTION: Change the parse opcode assigned to a node.  Usually used to
    230  *              change an opcode to DEFAULT_ARG so that the node is ignored
    231  *              during the code generation.  Also used to set generic integers
    232  *              to a specific size (8, 16, 32, or 64 bits)
    233  *
    234  ******************************************************************************/
    235 
    236 ACPI_PARSE_OBJECT *
    237 TrUpdateNode (
    238     UINT32                  ParseOpcode,
    239     ACPI_PARSE_OBJECT       *Op)
    240 {
    241 
    242     if (!Op)
    243     {
    244         return NULL;
    245     }
    246 
    247     DbgPrint (ASL_PARSE_OUTPUT,
    248         "\nUpdateNode: Old - %s, New - %s\n\n",
    249         UtGetOpName (Op->Asl.ParseOpcode),
    250         UtGetOpName (ParseOpcode));
    251 
    252     /* Assign new opcode and name */
    253 
    254     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
    255     {
    256         switch (ParseOpcode)
    257         {
    258         case PARSEOP_BYTECONST:
    259             Op->Asl.Value.Integer = 0xFF;
    260             break;
    261 
    262         case PARSEOP_WORDCONST:
    263             Op->Asl.Value.Integer = 0xFFFF;
    264             break;
    265 
    266         case PARSEOP_DWORDCONST:
    267             Op->Asl.Value.Integer = 0xFFFFFFFF;
    268             break;
    269 
    270         default:
    271             /* Don't care about others, don't need to check QWORD */
    272             break;
    273         }
    274     }
    275 
    276     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
    277     UtSetParseOpName (Op);
    278 
    279     /*
    280      * For the BYTE, WORD, and DWORD constants, make sure that the integer
    281      * that was passed in will actually fit into the data type
    282      */
    283     switch (ParseOpcode)
    284     {
    285     case PARSEOP_BYTECONST:
    286         Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
    287         break;
    288 
    289     case PARSEOP_WORDCONST:
    290         Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
    291         break;
    292 
    293     case PARSEOP_DWORDCONST:
    294         Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
    295         break;
    296 
    297     default:
    298         /* Don't care about others, don't need to check QWORD */
    299         break;
    300     }
    301 
    302     return Op;
    303 }
    304 
    305 
    306 /*******************************************************************************
    307  *
    308  * FUNCTION:    TrGetNodeFlagName
    309  *
    310  * PARAMETERS:  Flags               - Flags word to be decoded
    311  *
    312  * RETURN:      Name string. Always returns a valid string pointer.
    313  *
    314  * DESCRIPTION: Decode a flags word
    315  *
    316  ******************************************************************************/
    317 
    318 static char *
    319 TrGetNodeFlagName (
    320     UINT32                  Flags)
    321 {
    322 
    323     switch (Flags)
    324     {
    325     case NODE_VISITED:
    326         return ("NODE_VISITED");
    327 
    328     case NODE_AML_PACKAGE:
    329         return ("NODE_AML_PACKAGE");
    330 
    331     case NODE_IS_TARGET:
    332         return ("NODE_IS_TARGET");
    333 
    334     case NODE_IS_RESOURCE_DESC:
    335         return ("NODE_IS_RESOURCE_DESC");
    336 
    337     case NODE_IS_RESOURCE_FIELD:
    338         return ("NODE_IS_RESOURCE_FIELD");
    339 
    340     case NODE_HAS_NO_EXIT:
    341         return ("NODE_HAS_NO_EXIT");
    342 
    343     case NODE_IF_HAS_NO_EXIT:
    344         return ("NODE_IF_HAS_NO_EXIT");
    345 
    346     case NODE_NAME_INTERNALIZED:
    347         return ("NODE_NAME_INTERNALIZED");
    348 
    349     case NODE_METHOD_NO_RETVAL:
    350         return ("NODE_METHOD_NO_RETVAL");
    351 
    352     case NODE_METHOD_SOME_NO_RETVAL:
    353         return ("NODE_METHOD_SOME_NO_RETVAL");
    354 
    355     case NODE_RESULT_NOT_USED:
    356         return ("NODE_RESULT_NOT_USED");
    357 
    358     case NODE_METHOD_TYPED:
    359         return ("NODE_METHOD_TYPED");
    360 
    361     case NODE_IS_BIT_OFFSET:
    362         return ("NODE_IS_BIT_OFFSET");
    363 
    364     case NODE_COMPILE_TIME_CONST:
    365         return ("NODE_COMPILE_TIME_CONST");
    366 
    367     case NODE_IS_TERM_ARG:
    368         return ("NODE_IS_TERM_ARG");
    369 
    370     case NODE_WAS_ONES_OP:
    371         return ("NODE_WAS_ONES_OP");
    372 
    373     case NODE_IS_NAME_DECLARATION:
    374         return ("NODE_IS_NAME_DECLARATION");
    375 
    376     default:
    377         return ("Multiple Flags (or unknown flag) set");
    378     }
    379 }
    380 
    381 
    382 /*******************************************************************************
    383  *
    384  * FUNCTION:    TrSetNodeFlags
    385  *
    386  * PARAMETERS:  Op                  - An existing parse node
    387  *              Flags               - New flags word
    388  *
    389  * RETURN:      The updated parser op
    390  *
    391  * DESCRIPTION: Set bits in the node flags word.  Will not clear bits, only set
    392  *
    393  ******************************************************************************/
    394 
    395 ACPI_PARSE_OBJECT *
    396 TrSetNodeFlags (
    397     ACPI_PARSE_OBJECT       *Op,
    398     UINT32                  Flags)
    399 {
    400 
    401     DbgPrint (ASL_PARSE_OUTPUT,
    402         "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags,
    403         TrGetNodeFlagName (Flags));
    404 
    405     if (!Op)
    406     {
    407         return NULL;
    408     }
    409 
    410     Op->Asl.CompileFlags |= Flags;
    411 
    412     return Op;
    413 }
    414 
    415 
    416 /*******************************************************************************
    417  *
    418  * FUNCTION:    TrSetEndLineNumber
    419  *
    420  * PARAMETERS:  Op                - An existing parse node
    421  *
    422  * RETURN:      None.
    423  *
    424  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
    425  *              parse node to the current line numbers.
    426  *
    427  ******************************************************************************/
    428 
    429 void
    430 TrSetEndLineNumber (
    431     ACPI_PARSE_OBJECT       *Op)
    432 {
    433 
    434     /* If the end line # is already set, just return */
    435 
    436     if (Op->Asl.EndLine)
    437     {
    438         return;
    439     }
    440 
    441     Op->Asl.EndLine        = Gbl_CurrentLineNumber;
    442     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
    443 }
    444 
    445 
    446 /*******************************************************************************
    447  *
    448  * FUNCTION:    TrCreateLeafNode
    449  *
    450  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    451  *
    452  * RETURN:      Pointer to the new node.  Aborts on allocation failure
    453  *
    454  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
    455  *              assigned to the node)
    456  *
    457  ******************************************************************************/
    458 
    459 ACPI_PARSE_OBJECT *
    460 TrCreateLeafNode (
    461     UINT32                  ParseOpcode)
    462 {
    463     ACPI_PARSE_OBJECT       *Op;
    464 
    465 
    466     Op = TrAllocateNode (ParseOpcode);
    467 
    468     DbgPrint (ASL_PARSE_OUTPUT,
    469         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
    470         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode));
    471 
    472     return Op;
    473 }
    474 
    475 
    476 /*******************************************************************************
    477  *
    478  * FUNCTION:    TrCreateValuedLeafNode
    479  *
    480  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    481  *              Value               - Value to be assigned to the node
    482  *
    483  * RETURN:      Pointer to the new node.  Aborts on allocation failure
    484  *
    485  * DESCRIPTION: Create a leaf node (no children or peers) with a value
    486  *              assigned to it
    487  *
    488  ******************************************************************************/
    489 
    490 ACPI_PARSE_OBJECT *
    491 TrCreateValuedLeafNode (
    492     UINT32                  ParseOpcode,
    493     UINT64                  Value)
    494 {
    495     ACPI_PARSE_OBJECT       *Op;
    496 
    497 
    498     Op = TrAllocateNode (ParseOpcode);
    499 
    500     DbgPrint (ASL_PARSE_OUTPUT,
    501         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
    502         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
    503         ACPI_FORMAT_UINT64 (Value));
    504     Op->Asl.Value.Integer = Value;
    505 
    506     switch (ParseOpcode)
    507     {
    508     case PARSEOP_STRING_LITERAL:
    509         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
    510         break;
    511 
    512     case PARSEOP_NAMESEG:
    513         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
    514         break;
    515 
    516     case PARSEOP_NAMESTRING:
    517         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
    518         break;
    519 
    520     case PARSEOP_EISAID:
    521         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
    522         break;
    523 
    524     case PARSEOP_METHOD:
    525         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
    526         break;
    527 
    528     case PARSEOP_INTEGER:
    529         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER");
    530         break;
    531 
    532     default:
    533         break;
    534     }
    535 
    536     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    537     return Op;
    538 }
    539 
    540 
    541 /*******************************************************************************
    542  *
    543  * FUNCTION:    TrCreateNode
    544  *
    545  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
    546  *              NumChildren         - Number of children to follow
    547  *              ...                 - A list of child nodes to link to the new
    548  *                                    node.  NumChildren long.
    549  *
    550  * RETURN:      Pointer to the new node.  Aborts on allocation failure
    551  *
    552  * DESCRIPTION: Create a new parse node and link together a list of child
    553  *              nodes underneath the new node.
    554  *
    555  ******************************************************************************/
    556 
    557 ACPI_PARSE_OBJECT *
    558 TrCreateNode (
    559     UINT32                  ParseOpcode,
    560     UINT32                  NumChildren,
    561     ...)
    562 {
    563     ACPI_PARSE_OBJECT       *Op;
    564     ACPI_PARSE_OBJECT       *Child;
    565     ACPI_PARSE_OBJECT       *PrevChild;
    566     va_list                 ap;
    567     UINT32                  i;
    568     BOOLEAN                 FirstChild;
    569 
    570 
    571     va_start (ap, NumChildren);
    572 
    573     /* Allocate one new node */
    574 
    575     Op = TrAllocateNode (ParseOpcode);
    576 
    577     DbgPrint (ASL_PARSE_OUTPUT,
    578         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
    579         Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode));
    580 
    581     /* Some extra debug output based on the parse opcode */
    582 
    583     switch (ParseOpcode)
    584     {
    585     case PARSEOP_DEFINITIONBLOCK:
    586         RootNode = Op;
    587         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
    588         break;
    589 
    590     case PARSEOP_OPERATIONREGION:
    591         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
    592         break;
    593 
    594     case PARSEOP_OR:
    595         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
    596         break;
    597 
    598     default:
    599         /* Nothing to do for other opcodes */
    600         break;
    601     }
    602 
    603     /* Link the new node to its children */
    604 
    605     PrevChild = NULL;
    606     FirstChild = TRUE;
    607     for (i = 0; i < NumChildren; i++)
    608     {
    609         /* Get the next child */
    610 
    611         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
    612         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
    613 
    614         /*
    615          * If child is NULL, this means that an optional argument
    616          * was omitted.  We must create a placeholder with a special
    617          * opcode (DEFAULT_ARG) so that the code generator will know
    618          * that it must emit the correct default for this argument
    619          */
    620         if (!Child)
    621         {
    622             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
    623         }
    624 
    625         /* Link first child to parent */
    626 
    627         if (FirstChild)
    628         {
    629             FirstChild = FALSE;
    630             Op->Asl.Child = Child;
    631         }
    632 
    633         /* Point all children to parent */
    634 
    635         Child->Asl.Parent = Op;
    636 
    637         /* Link children in a peer list */
    638 
    639         if (PrevChild)
    640         {
    641             PrevChild->Asl.Next = Child;
    642         };
    643 
    644         /*
    645          * This child might be a list, point all nodes in the list
    646          * to the same parent
    647          */
    648         while (Child->Asl.Next)
    649         {
    650             Child = Child->Asl.Next;
    651             Child->Asl.Parent = Op;
    652         }
    653 
    654         PrevChild = Child;
    655     }
    656     va_end(ap);
    657 
    658     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    659     return Op;
    660 }
    661 
    662 
    663 /*******************************************************************************
    664  *
    665  * FUNCTION:    TrLinkChildren
    666  *
    667  * PARAMETERS:  Op                - An existing parse node
    668  *              NumChildren         - Number of children to follow
    669  *              ...                 - A list of child nodes to link to the new
    670  *                                    node.  NumChildren long.
    671  *
    672  * RETURN:      The updated (linked) node
    673  *
    674  * DESCRIPTION: Link a group of nodes to an existing parse node
    675  *
    676  ******************************************************************************/
    677 
    678 ACPI_PARSE_OBJECT *
    679 TrLinkChildren (
    680     ACPI_PARSE_OBJECT       *Op,
    681     UINT32                  NumChildren,
    682     ...)
    683 {
    684     ACPI_PARSE_OBJECT       *Child;
    685     ACPI_PARSE_OBJECT       *PrevChild;
    686     va_list                 ap;
    687     UINT32                  i;
    688     BOOLEAN                 FirstChild;
    689 
    690 
    691     va_start (ap, NumChildren);
    692 
    693 
    694     TrSetEndLineNumber (Op);
    695 
    696     DbgPrint (ASL_PARSE_OUTPUT,
    697         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
    698         Op->Asl.LineNumber, Op->Asl.EndLine,
    699         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
    700 
    701     switch (Op->Asl.ParseOpcode)
    702     {
    703     case PARSEOP_DEFINITIONBLOCK:
    704         RootNode = Op;
    705         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
    706         break;
    707 
    708     case PARSEOP_OPERATIONREGION:
    709         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
    710         break;
    711 
    712     case PARSEOP_OR:
    713         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
    714         break;
    715 
    716     default:
    717         /* Nothing to do for other opcodes */
    718         break;
    719     }
    720 
    721     /* Link the new node to it's children */
    722 
    723     PrevChild = NULL;
    724     FirstChild = TRUE;
    725     for (i = 0; i < NumChildren; i++)
    726     {
    727         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
    728 
    729         if ((Child == PrevChild) && (Child != NULL))
    730         {
    731             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
    732                 "Child node list invalid");
    733             return Op;
    734         }
    735 
    736         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
    737 
    738         /*
    739          * If child is NULL, this means that an optional argument
    740          * was omitted.  We must create a placeholder with a special
    741          * opcode (DEFAULT_ARG) so that the code generator will know
    742          * that it must emit the correct default for this argument
    743          */
    744         if (!Child)
    745         {
    746             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
    747         }
    748 
    749         /* Link first child to parent */
    750 
    751         if (FirstChild)
    752         {
    753             FirstChild = FALSE;
    754             Op->Asl.Child = Child;
    755         }
    756 
    757         /* Point all children to parent */
    758 
    759         Child->Asl.Parent = Op;
    760 
    761         /* Link children in a peer list */
    762 
    763         if (PrevChild)
    764         {
    765             PrevChild->Asl.Next = Child;
    766         };
    767 
    768         /*
    769          * This child might be a list, point all nodes in the list
    770          * to the same parent
    771          */
    772         while (Child->Asl.Next)
    773         {
    774             Child = Child->Asl.Next;
    775             Child->Asl.Parent = Op;
    776         }
    777         PrevChild = Child;
    778     }
    779     va_end(ap);
    780 
    781     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    782     return Op;
    783 }
    784 
    785 
    786 /*******************************************************************************
    787  *
    788  * FUNCTION:    TrLinkPeerNode
    789  *
    790  * PARAMETERS:  Op1           - First peer
    791  *              Op2           - Second peer
    792  *
    793  * RETURN:      Op1 or the non-null node.
    794  *
    795  * DESCRIPTION: Link two nodes as peers.  Handles cases where one peer is null.
    796  *
    797  ******************************************************************************/
    798 
    799 ACPI_PARSE_OBJECT *
    800 TrLinkPeerNode (
    801     ACPI_PARSE_OBJECT       *Op1,
    802     ACPI_PARSE_OBJECT       *Op2)
    803 {
    804     ACPI_PARSE_OBJECT       *Next;
    805 
    806 
    807     DbgPrint (ASL_PARSE_OUTPUT,
    808         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n",
    809         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
    810         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
    811 
    812 
    813     if ((!Op1) && (!Op2))
    814     {
    815         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
    816         return Op1;
    817     }
    818 
    819     /* If one of the nodes is null, just return the non-null node */
    820 
    821     if (!Op2)
    822     {
    823         return Op1;
    824     }
    825 
    826     if (!Op1)
    827     {
    828         return Op2;
    829     }
    830 
    831     if (Op1 == Op2)
    832     {
    833         DbgPrint (ASL_DEBUG_OUTPUT,
    834             "\n\n************* Internal error, linking node to itself %p\n\n\n",
    835             Op1);
    836         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
    837             "Linking node to itself");
    838         return Op1;
    839     }
    840 
    841     Op1->Asl.Parent = Op2->Asl.Parent;
    842 
    843     /*
    844      * Op 1 may already have a peer list (such as an IF/ELSE pair),
    845      * so we must walk to the end of the list and attach the new
    846      * peer at the end
    847      */
    848     Next = Op1;
    849     while (Next->Asl.Next)
    850     {
    851         Next = Next->Asl.Next;
    852     }
    853 
    854     Next->Asl.Next = Op2;
    855     return Op1;
    856 }
    857 
    858 
    859 /*******************************************************************************
    860  *
    861  * FUNCTION:    TrLinkPeerNodes
    862  *
    863  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
    864  *              ...                 - A list of nodes to link together as peers
    865  *
    866  * RETURN:      The first node in the list (head of the peer list)
    867  *
    868  * DESCRIPTION: Link together an arbitrary number of peer nodes.
    869  *
    870  ******************************************************************************/
    871 
    872 ACPI_PARSE_OBJECT *
    873 TrLinkPeerNodes (
    874     UINT32                  NumPeers,
    875     ...)
    876 {
    877     ACPI_PARSE_OBJECT       *This;
    878     ACPI_PARSE_OBJECT       *Next;
    879     va_list                 ap;
    880     UINT32                  i;
    881     ACPI_PARSE_OBJECT       *Start;
    882 
    883 
    884     DbgPrint (ASL_PARSE_OUTPUT,
    885         "\nLinkPeerNodes: (%u) ", NumPeers);
    886 
    887     va_start (ap, NumPeers);
    888     This = va_arg (ap, ACPI_PARSE_OBJECT *);
    889     Start = This;
    890 
    891     /*
    892      * Link all peers
    893      */
    894     for (i = 0; i < (NumPeers -1); i++)
    895     {
    896         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
    897 
    898         while (This->Asl.Next)
    899         {
    900             This = This->Asl.Next;
    901         }
    902 
    903         /* Get another peer node */
    904 
    905         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
    906         if (!Next)
    907         {
    908             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
    909         }
    910 
    911         /* link new node to the current node */
    912 
    913         This->Asl.Next = Next;
    914         This = Next;
    915     }
    916     va_end (ap);
    917 
    918     DbgPrint (ASL_PARSE_OUTPUT,"\n\n");
    919     return (Start);
    920 }
    921 
    922 
    923 /*******************************************************************************
    924  *
    925  * FUNCTION:    TrLinkChildNode
    926  *
    927  * PARAMETERS:  Op1           - Parent node
    928  *              Op2           - Op to become a child
    929  *
    930  * RETURN:      The parent node
    931  *
    932  * DESCRIPTION: Link two nodes together as a parent and child
    933  *
    934  ******************************************************************************/
    935 
    936 ACPI_PARSE_OBJECT *
    937 TrLinkChildNode (
    938     ACPI_PARSE_OBJECT       *Op1,
    939     ACPI_PARSE_OBJECT       *Op2)
    940 {
    941     ACPI_PARSE_OBJECT       *Next;
    942 
    943 
    944     DbgPrint (ASL_PARSE_OUTPUT,
    945         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n",
    946         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
    947         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
    948 
    949     if (!Op1 || !Op2)
    950     {
    951         return Op1;
    952     }
    953 
    954     Op1->Asl.Child = Op2;
    955 
    956     /* Set the child and all peers of the child to point to the parent */
    957 
    958     Next = Op2;
    959     while (Next)
    960     {
    961         Next->Asl.Parent = Op1;
    962         Next = Next->Asl.Next;
    963     }
    964 
    965     return Op1;
    966 }
    967 
    968 
    969 /*******************************************************************************
    970  *
    971  * FUNCTION:    TrWalkParseTree
    972  *
    973  * PARAMETERS:  Visitation              - Type of walk
    974  *              DescendingCallback      - Called during tree descent
    975  *              AscendingCallback       - Called during tree ascent
    976  *              Context                 - To be passed to the callbacks
    977  *
    978  * RETURN:      Status from callback(s)
    979  *
    980  * DESCRIPTION: Walk the entire parse tree.
    981  *
    982  ******************************************************************************/
    983 
    984 ACPI_STATUS
    985 TrWalkParseTree (
    986     ACPI_PARSE_OBJECT       *Op,
    987     UINT32                  Visitation,
    988     ASL_WALK_CALLBACK       DescendingCallback,
    989     ASL_WALK_CALLBACK       AscendingCallback,
    990     void                    *Context)
    991 {
    992     UINT32                  Level;
    993     BOOLEAN                 NodePreviouslyVisited;
    994     ACPI_PARSE_OBJECT       *StartOp = Op;
    995     ACPI_STATUS             Status;
    996 
    997 
    998     if (!RootNode)
    999     {
   1000         return (AE_OK);
   1001     }
   1002 
   1003     Level = 0;
   1004     NodePreviouslyVisited = FALSE;
   1005 
   1006     switch (Visitation)
   1007     {
   1008     case ASL_WALK_VISIT_DOWNWARD:
   1009 
   1010         while (Op)
   1011         {
   1012             if (!NodePreviouslyVisited)
   1013             {
   1014                 /* Let the callback process the node. */
   1015 
   1016                 Status = DescendingCallback (Op, Level, Context);
   1017                 if (ACPI_SUCCESS (Status))
   1018                 {
   1019                     /* Visit children first, once */
   1020 
   1021                     if (Op->Asl.Child)
   1022                     {
   1023                         Level++;
   1024                         Op = Op->Asl.Child;
   1025                         continue;
   1026                     }
   1027                 }
   1028                 else if (Status != AE_CTRL_DEPTH)
   1029                 {
   1030                     /* Exit immediately on any error */
   1031 
   1032                     return (Status);
   1033                 }
   1034             }
   1035 
   1036             /* Terminate walk at start op */
   1037 
   1038             if (Op == StartOp)
   1039             {
   1040                 break;
   1041             }
   1042 
   1043             /* No more children, visit peers */
   1044 
   1045             if (Op->Asl.Next)
   1046             {
   1047                 Op = Op->Asl.Next;
   1048                 NodePreviouslyVisited = FALSE;
   1049             }
   1050             else
   1051             {
   1052                 /* No children or peers, re-visit parent */
   1053 
   1054                 if (Level != 0 )
   1055                 {
   1056                     Level--;
   1057                 }
   1058                 Op = Op->Asl.Parent;
   1059                 NodePreviouslyVisited = TRUE;
   1060             }
   1061         }
   1062         break;
   1063 
   1064 
   1065     case ASL_WALK_VISIT_UPWARD:
   1066 
   1067         while (Op)
   1068         {
   1069             /* Visit leaf node (no children) or parent node on return trip */
   1070 
   1071             if ((!Op->Asl.Child) ||
   1072                 (NodePreviouslyVisited))
   1073             {
   1074                 /* Let the callback process the node. */
   1075 
   1076                 Status = AscendingCallback (Op, Level, Context);
   1077                 if (ACPI_FAILURE (Status))
   1078                 {
   1079                     return (Status);
   1080                 }
   1081             }
   1082             else
   1083             {
   1084                 /* Visit children first, once */
   1085 
   1086                 Level++;
   1087                 Op = Op->Asl.Child;
   1088                 continue;
   1089             }
   1090 
   1091             /* Terminate walk at start op */
   1092 
   1093             if (Op == StartOp)
   1094             {
   1095                 break;
   1096             }
   1097 
   1098             /* No more children, visit peers */
   1099 
   1100             if (Op->Asl.Next)
   1101             {
   1102                 Op = Op->Asl.Next;
   1103                 NodePreviouslyVisited = FALSE;
   1104             }
   1105             else
   1106             {
   1107                 /* No children or peers, re-visit parent */
   1108 
   1109                 if (Level != 0 )
   1110                 {
   1111                     Level--;
   1112                 }
   1113                 Op = Op->Asl.Parent;
   1114                 NodePreviouslyVisited = TRUE;
   1115             }
   1116         }
   1117         break;
   1118 
   1119 
   1120      case ASL_WALK_VISIT_TWICE:
   1121 
   1122         while (Op)
   1123         {
   1124             if (NodePreviouslyVisited)
   1125             {
   1126                 Status = AscendingCallback (Op, Level, Context);
   1127                 if (ACPI_FAILURE (Status))
   1128                 {
   1129                     return (Status);
   1130                 }
   1131             }
   1132             else
   1133             {
   1134                 /* Let the callback process the node. */
   1135 
   1136                 Status = DescendingCallback (Op, Level, Context);
   1137                 if (ACPI_SUCCESS (Status))
   1138                 {
   1139                     /* Visit children first, once */
   1140 
   1141                     if (Op->Asl.Child)
   1142                     {
   1143                         Level++;
   1144                         Op = Op->Asl.Child;
   1145                         continue;
   1146                     }
   1147                 }
   1148                 else if (Status != AE_CTRL_DEPTH)
   1149                 {
   1150                     /* Exit immediately on any error */
   1151 
   1152                     return (Status);
   1153                 }
   1154             }
   1155 
   1156             /* Terminate walk at start op */
   1157 
   1158             if (Op == StartOp)
   1159             {
   1160                 break;
   1161             }
   1162 
   1163             /* No more children, visit peers */
   1164 
   1165             if (Op->Asl.Next)
   1166             {
   1167                 Op = Op->Asl.Next;
   1168                 NodePreviouslyVisited = FALSE;
   1169             }
   1170             else
   1171             {
   1172                 /* No children or peers, re-visit parent */
   1173 
   1174                 if (Level != 0 )
   1175                 {
   1176                     Level--;
   1177                 }
   1178                 Op = Op->Asl.Parent;
   1179                 NodePreviouslyVisited = TRUE;
   1180             }
   1181         }
   1182         break;
   1183 
   1184     default:
   1185         /* No other types supported */
   1186         break;
   1187     }
   1188 
   1189     /* If we get here, the walk completed with no errors */
   1190 
   1191     return (AE_OK);
   1192 }
   1193 
   1194 
   1195