Home | History | Annotate | Line # | Download | only in compiler
asltree.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: asltree - parse tree management
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 
     45 #include "aslcompiler.h"
     46 #include "aslcompiler.y.h"
     47 #include "acapps.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 static char *
     60 TrGetNodeFlagName (
     61     UINT32                  Flags);
     62 
     63 
     64 /*******************************************************************************
     65  *
     66  * FUNCTION:    TrGetNextNode
     67  *
     68  * PARAMETERS:  None
     69  *
     70  * RETURN:      New parse node. Aborts on allocation failure
     71  *
     72  * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
     73  *              dynamic memory manager for performance reasons (This has a
     74  *              major impact on the speed of the compiler.)
     75  *
     76  ******************************************************************************/
     77 
     78 static ACPI_PARSE_OBJECT *
     79 TrGetNextNode (
     80     void)
     81 {
     82 
     83     if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast)
     84     {
     85         Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) *
     86                                 ASL_NODE_CACHE_SIZE);
     87         Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE;
     88     }
     89 
     90     return (Gbl_NodeCacheNext++);
     91 }
     92 
     93 
     94 /*******************************************************************************
     95  *
     96  * FUNCTION:    TrAllocateNode
     97  *
     98  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
     99  *
    100  * RETURN:      New parse node. Aborts on allocation failure
    101  *
    102  * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
    103  *
    104  ******************************************************************************/
    105 
    106 ACPI_PARSE_OBJECT *
    107 TrAllocateNode (
    108     UINT32                  ParseOpcode)
    109 {
    110     ACPI_PARSE_OBJECT       *Op;
    111 
    112 
    113     Op = TrGetNextNode ();
    114 
    115     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
    116     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
    117     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
    118     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
    119     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
    120     Op->Asl.Column            = Gbl_CurrentColumn;
    121 
    122     UtSetParseOpName (Op);
    123     return (Op);
    124 }
    125 
    126 
    127 /*******************************************************************************
    128  *
    129  * FUNCTION:    TrReleaseNode
    130  *
    131  * PARAMETERS:  Op            - Op to be released
    132  *
    133  * RETURN:      None
    134  *
    135  * DESCRIPTION: "release" a node. In truth, nothing is done since the node
    136  *              is part of a larger buffer
    137  *
    138  ******************************************************************************/
    139 
    140 void
    141 TrReleaseNode (
    142     ACPI_PARSE_OBJECT       *Op)
    143 {
    144 
    145     return;
    146 }
    147 
    148 
    149 /*******************************************************************************
    150  *
    151  * FUNCTION:    TrUpdateNode
    152  *
    153  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    154  *              Op                - An existing parse node
    155  *
    156  * RETURN:      The updated node
    157  *
    158  * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
    159  *              change an opcode to DEFAULT_ARG so that the node is ignored
    160  *              during the code generation. Also used to set generic integers
    161  *              to a specific size (8, 16, 32, or 64 bits)
    162  *
    163  ******************************************************************************/
    164 
    165 ACPI_PARSE_OBJECT *
    166 TrUpdateNode (
    167     UINT32                  ParseOpcode,
    168     ACPI_PARSE_OBJECT       *Op)
    169 {
    170 
    171     if (!Op)
    172     {
    173         return (NULL);
    174     }
    175 
    176     DbgPrint (ASL_PARSE_OUTPUT,
    177         "\nUpdateNode: Old - %s, New - %s\n\n",
    178         UtGetOpName (Op->Asl.ParseOpcode),
    179         UtGetOpName (ParseOpcode));
    180 
    181     /* Assign new opcode and name */
    182 
    183     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
    184     {
    185         switch (ParseOpcode)
    186         {
    187         case PARSEOP_BYTECONST:
    188 
    189             Op->Asl.Value.Integer = ACPI_UINT8_MAX;
    190             break;
    191 
    192         case PARSEOP_WORDCONST:
    193 
    194             Op->Asl.Value.Integer = ACPI_UINT16_MAX;
    195             break;
    196 
    197         case PARSEOP_DWORDCONST:
    198 
    199             Op->Asl.Value.Integer = ACPI_UINT32_MAX;
    200             break;
    201 
    202         /* Don't need to do the QWORD case */
    203 
    204         default:
    205 
    206             /* Don't care about others */
    207             break;
    208         }
    209     }
    210 
    211     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
    212     UtSetParseOpName (Op);
    213 
    214     /*
    215      * For the BYTE, WORD, and DWORD constants, make sure that the integer
    216      * that was passed in will actually fit into the data type
    217      */
    218     switch (ParseOpcode)
    219     {
    220     case PARSEOP_BYTECONST:
    221 
    222         UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
    223         Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
    224         break;
    225 
    226     case PARSEOP_WORDCONST:
    227 
    228         UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
    229         Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
    230         break;
    231 
    232     case PARSEOP_DWORDCONST:
    233 
    234         UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
    235         Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
    236         break;
    237 
    238     default:
    239 
    240         /* Don't care about others, don't need to check QWORD */
    241 
    242         break;
    243     }
    244 
    245     return (Op);
    246 }
    247 
    248 
    249 /*******************************************************************************
    250  *
    251  * FUNCTION:    TrGetNodeFlagName
    252  *
    253  * PARAMETERS:  Flags               - Flags word to be decoded
    254  *
    255  * RETURN:      Name string. Always returns a valid string pointer.
    256  *
    257  * DESCRIPTION: Decode a flags word
    258  *
    259  ******************************************************************************/
    260 
    261 static char *
    262 TrGetNodeFlagName (
    263     UINT32                  Flags)
    264 {
    265 
    266     switch (Flags)
    267     {
    268     case NODE_VISITED:
    269 
    270         return ("NODE_VISITED");
    271 
    272     case NODE_AML_PACKAGE:
    273 
    274         return ("NODE_AML_PACKAGE");
    275 
    276     case NODE_IS_TARGET:
    277 
    278         return ("NODE_IS_TARGET");
    279 
    280     case NODE_IS_RESOURCE_DESC:
    281 
    282         return ("NODE_IS_RESOURCE_DESC");
    283 
    284     case NODE_IS_RESOURCE_FIELD:
    285 
    286         return ("NODE_IS_RESOURCE_FIELD");
    287 
    288     case NODE_HAS_NO_EXIT:
    289 
    290         return ("NODE_HAS_NO_EXIT");
    291 
    292     case NODE_IF_HAS_NO_EXIT:
    293 
    294         return ("NODE_IF_HAS_NO_EXIT");
    295 
    296     case NODE_NAME_INTERNALIZED:
    297 
    298         return ("NODE_NAME_INTERNALIZED");
    299 
    300     case NODE_METHOD_NO_RETVAL:
    301 
    302         return ("NODE_METHOD_NO_RETVAL");
    303 
    304     case NODE_METHOD_SOME_NO_RETVAL:
    305 
    306         return ("NODE_METHOD_SOME_NO_RETVAL");
    307 
    308     case NODE_RESULT_NOT_USED:
    309 
    310         return ("NODE_RESULT_NOT_USED");
    311 
    312     case NODE_METHOD_TYPED:
    313 
    314         return ("NODE_METHOD_TYPED");
    315 
    316     case NODE_COMPILE_TIME_CONST:
    317 
    318         return ("NODE_COMPILE_TIME_CONST");
    319 
    320     case NODE_IS_TERM_ARG:
    321 
    322         return ("NODE_IS_TERM_ARG");
    323 
    324     case NODE_WAS_ONES_OP:
    325 
    326         return ("NODE_WAS_ONES_OP");
    327 
    328     case NODE_IS_NAME_DECLARATION:
    329 
    330         return ("NODE_IS_NAME_DECLARATION");
    331 
    332     default:
    333 
    334         return ("Multiple Flags (or unknown flag) set");
    335     }
    336 }
    337 
    338 
    339 /*******************************************************************************
    340  *
    341  * FUNCTION:    TrSetNodeFlags
    342  *
    343  * PARAMETERS:  Op                  - An existing parse node
    344  *              Flags               - New flags word
    345  *
    346  * RETURN:      The updated parser op
    347  *
    348  * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
    349  *
    350  ******************************************************************************/
    351 
    352 ACPI_PARSE_OBJECT *
    353 TrSetNodeFlags (
    354     ACPI_PARSE_OBJECT       *Op,
    355     UINT32                  Flags)
    356 {
    357 
    358     DbgPrint (ASL_PARSE_OUTPUT,
    359         "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags,
    360         TrGetNodeFlagName (Flags));
    361 
    362     if (!Op)
    363     {
    364         return (NULL);
    365     }
    366 
    367     Op->Asl.CompileFlags |= Flags;
    368     return (Op);
    369 }
    370 
    371 
    372 /*******************************************************************************
    373  *
    374  * FUNCTION:    TrSetNodeAmlLength
    375  *
    376  * PARAMETERS:  Op                  - An existing parse node
    377  *              Length              - AML Length
    378  *
    379  * RETURN:      The updated parser op
    380  *
    381  * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
    382  *              the presence of a node that must be reduced to a fixed length
    383  *              constant.
    384  *
    385  ******************************************************************************/
    386 
    387 ACPI_PARSE_OBJECT *
    388 TrSetNodeAmlLength (
    389     ACPI_PARSE_OBJECT       *Op,
    390     UINT32                  Length)
    391 {
    392 
    393     DbgPrint (ASL_PARSE_OUTPUT,
    394         "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
    395 
    396     if (!Op)
    397     {
    398         return (NULL);
    399     }
    400 
    401     Op->Asl.AmlLength = Length;
    402     return (Op);
    403 }
    404 
    405 
    406 /*******************************************************************************
    407  *
    408  * FUNCTION:    TrSetEndLineNumber
    409  *
    410  * PARAMETERS:  Op                - An existing parse node
    411  *
    412  * RETURN:      None.
    413  *
    414  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
    415  *              parse node to the current line numbers.
    416  *
    417  ******************************************************************************/
    418 
    419 void
    420 TrSetEndLineNumber (
    421     ACPI_PARSE_OBJECT       *Op)
    422 {
    423 
    424     /* If the end line # is already set, just return */
    425 
    426     if (Op->Asl.EndLine)
    427     {
    428         return;
    429     }
    430 
    431     Op->Asl.EndLine        = Gbl_CurrentLineNumber;
    432     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
    433 }
    434 
    435 
    436 /*******************************************************************************
    437  *
    438  * FUNCTION:    TrCreateLeafNode
    439  *
    440  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    441  *
    442  * RETURN:      Pointer to the new node. Aborts on allocation failure
    443  *
    444  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
    445  *              assigned to the node)
    446  *
    447  ******************************************************************************/
    448 
    449 ACPI_PARSE_OBJECT *
    450 TrCreateLeafNode (
    451     UINT32                  ParseOpcode)
    452 {
    453     ACPI_PARSE_OBJECT       *Op;
    454 
    455 
    456     Op = TrAllocateNode (ParseOpcode);
    457 
    458     DbgPrint (ASL_PARSE_OUTPUT,
    459         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
    460         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode));
    461 
    462     return (Op);
    463 }
    464 
    465 
    466 /*******************************************************************************
    467  *
    468  * FUNCTION:    TrCreateConstantLeafNode
    469  *
    470  * PARAMETERS:  ParseOpcode         - The constant opcode
    471  *
    472  * RETURN:      Pointer to the new node. Aborts on allocation failure
    473  *
    474  * DESCRIPTION: Create a leaf node (no children or peers) for one of the
    475  *              special constants - __LINE__, __FILE__, and __DATE__.
    476  *
    477  * Note: An implemenation of __FUNC__ cannot happen here because we don't
    478  * have a full parse tree at this time and cannot find the parent control
    479  * method. If it is ever needed, __FUNC__ must be implemented later, after
    480  * the parse tree has been fully constructed.
    481  *
    482  ******************************************************************************/
    483 
    484 ACPI_PARSE_OBJECT *
    485 TrCreateConstantLeafNode (
    486     UINT32                  ParseOpcode)
    487 {
    488     ACPI_PARSE_OBJECT       *Op = NULL;
    489     time_t                  CurrentTime;
    490     char                    *StaticTimeString;
    491     char                    *TimeString;
    492     char                    *Path;
    493     char                    *Filename;
    494 
    495 
    496     switch (ParseOpcode)
    497     {
    498     case PARSEOP___LINE__:
    499 
    500         Op = TrAllocateNode (PARSEOP_INTEGER);
    501         Op->Asl.Value.Integer = Op->Asl.LineNumber;
    502         break;
    503 
    504     case PARSEOP___PATH__:
    505 
    506         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    507 
    508         /* Op.Asl.Filename contains the full pathname to the file */
    509 
    510         Op->Asl.Value.String = Op->Asl.Filename;
    511         break;
    512 
    513     case PARSEOP___FILE__:
    514 
    515         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    516 
    517         /* Get the simple filename from the full path */
    518 
    519         FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename);
    520         ACPI_FREE (Path);
    521         Op->Asl.Value.String = Filename;
    522         break;
    523 
    524     case PARSEOP___DATE__:
    525 
    526         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
    527 
    528         /* Get a copy of the current time */
    529 
    530         CurrentTime = time (NULL);
    531         StaticTimeString = ctime (&CurrentTime);
    532         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
    533         strcpy (TimeString, StaticTimeString);
    534 
    535         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
    536         Op->Asl.Value.String = TimeString;
    537         break;
    538 
    539     default: /* This would be an internal error */
    540 
    541         return (NULL);
    542     }
    543 
    544     DbgPrint (ASL_PARSE_OUTPUT,
    545         "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
    546         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
    547         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
    548     return (Op);
    549 }
    550 
    551 
    552 /*******************************************************************************
    553  *
    554  * FUNCTION:    TrCreateValuedLeafNode
    555  *
    556  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
    557  *              Value               - Value to be assigned to the node
    558  *
    559  * RETURN:      Pointer to the new node. Aborts on allocation failure
    560  *
    561  * DESCRIPTION: Create a leaf node (no children or peers) with a value
    562  *              assigned to it
    563  *
    564  ******************************************************************************/
    565 
    566 ACPI_PARSE_OBJECT *
    567 TrCreateValuedLeafNode (
    568     UINT32                  ParseOpcode,
    569     UINT64                  Value)
    570 {
    571     ACPI_PARSE_OBJECT       *Op;
    572 
    573 
    574     Op = TrAllocateNode (ParseOpcode);
    575 
    576     DbgPrint (ASL_PARSE_OUTPUT,
    577         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
    578         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
    579         ACPI_FORMAT_UINT64 (Value));
    580     Op->Asl.Value.Integer = Value;
    581 
    582     switch (ParseOpcode)
    583     {
    584     case PARSEOP_STRING_LITERAL:
    585 
    586         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
    587         break;
    588 
    589     case PARSEOP_NAMESEG:
    590 
    591         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
    592         break;
    593 
    594     case PARSEOP_NAMESTRING:
    595 
    596         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
    597         break;
    598 
    599     case PARSEOP_EISAID:
    600 
    601         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
    602         break;
    603 
    604     case PARSEOP_METHOD:
    605 
    606         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
    607         break;
    608 
    609     case PARSEOP_INTEGER:
    610 
    611         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER");
    612         break;
    613 
    614     default:
    615 
    616         break;
    617     }
    618 
    619     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    620     return (Op);
    621 }
    622 
    623 
    624 /*******************************************************************************
    625  *
    626  * FUNCTION:    TrCreateNode
    627  *
    628  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
    629  *              NumChildren         - Number of children to follow
    630  *              ...                 - A list of child nodes to link to the new
    631  *                                    node. NumChildren long.
    632  *
    633  * RETURN:      Pointer to the new node. Aborts on allocation failure
    634  *
    635  * DESCRIPTION: Create a new parse node and link together a list of child
    636  *              nodes underneath the new node.
    637  *
    638  ******************************************************************************/
    639 
    640 ACPI_PARSE_OBJECT *
    641 TrCreateNode (
    642     UINT32                  ParseOpcode,
    643     UINT32                  NumChildren,
    644     ...)
    645 {
    646     ACPI_PARSE_OBJECT       *Op;
    647     ACPI_PARSE_OBJECT       *Child;
    648     ACPI_PARSE_OBJECT       *PrevChild;
    649     va_list                 ap;
    650     UINT32                  i;
    651     BOOLEAN                 FirstChild;
    652 
    653 
    654     va_start (ap, NumChildren);
    655 
    656     /* Allocate one new node */
    657 
    658     Op = TrAllocateNode (ParseOpcode);
    659 
    660     DbgPrint (ASL_PARSE_OUTPUT,
    661         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
    662         Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode));
    663 
    664     /* Some extra debug output based on the parse opcode */
    665 
    666     switch (ParseOpcode)
    667     {
    668     case PARSEOP_DEFINITIONBLOCK:
    669 
    670         RootNode = Op;
    671         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
    672         break;
    673 
    674     case PARSEOP_OPERATIONREGION:
    675 
    676         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
    677         break;
    678 
    679     case PARSEOP_OR:
    680 
    681         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
    682         break;
    683 
    684     default:
    685 
    686         /* Nothing to do for other opcodes */
    687 
    688         break;
    689     }
    690 
    691     /* Link the new node to its children */
    692 
    693     PrevChild = NULL;
    694     FirstChild = TRUE;
    695     for (i = 0; i < NumChildren; i++)
    696     {
    697         /* Get the next child */
    698 
    699         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
    700         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
    701 
    702         /*
    703          * If child is NULL, this means that an optional argument
    704          * was omitted. We must create a placeholder with a special
    705          * opcode (DEFAULT_ARG) so that the code generator will know
    706          * that it must emit the correct default for this argument
    707          */
    708         if (!Child)
    709         {
    710             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
    711         }
    712 
    713         /* Link first child to parent */
    714 
    715         if (FirstChild)
    716         {
    717             FirstChild = FALSE;
    718             Op->Asl.Child = Child;
    719         }
    720 
    721         /* Point all children to parent */
    722 
    723         Child->Asl.Parent = Op;
    724 
    725         /* Link children in a peer list */
    726 
    727         if (PrevChild)
    728         {
    729             PrevChild->Asl.Next = Child;
    730         };
    731 
    732         /*
    733          * This child might be a list, point all nodes in the list
    734          * to the same parent
    735          */
    736         while (Child->Asl.Next)
    737         {
    738             Child = Child->Asl.Next;
    739             Child->Asl.Parent = Op;
    740         }
    741 
    742         PrevChild = Child;
    743     }
    744     va_end(ap);
    745 
    746     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    747     return (Op);
    748 }
    749 
    750 
    751 /*******************************************************************************
    752  *
    753  * FUNCTION:    TrLinkChildren
    754  *
    755  * PARAMETERS:  Op                - An existing parse node
    756  *              NumChildren         - Number of children to follow
    757  *              ...                 - A list of child nodes to link to the new
    758  *                                    node. NumChildren long.
    759  *
    760  * RETURN:      The updated (linked) node
    761  *
    762  * DESCRIPTION: Link a group of nodes to an existing parse node
    763  *
    764  ******************************************************************************/
    765 
    766 ACPI_PARSE_OBJECT *
    767 TrLinkChildren (
    768     ACPI_PARSE_OBJECT       *Op,
    769     UINT32                  NumChildren,
    770     ...)
    771 {
    772     ACPI_PARSE_OBJECT       *Child;
    773     ACPI_PARSE_OBJECT       *PrevChild;
    774     va_list                 ap;
    775     UINT32                  i;
    776     BOOLEAN                 FirstChild;
    777 
    778 
    779     va_start (ap, NumChildren);
    780 
    781 
    782     TrSetEndLineNumber (Op);
    783 
    784     DbgPrint (ASL_PARSE_OUTPUT,
    785         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
    786         Op->Asl.LineNumber, Op->Asl.EndLine,
    787         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
    788 
    789     switch (Op->Asl.ParseOpcode)
    790     {
    791     case PARSEOP_DEFINITIONBLOCK:
    792 
    793         RootNode = Op;
    794         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
    795         break;
    796 
    797     case PARSEOP_OPERATIONREGION:
    798 
    799         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
    800         break;
    801 
    802     case PARSEOP_OR:
    803 
    804         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
    805         break;
    806 
    807     default:
    808 
    809         /* Nothing to do for other opcodes */
    810 
    811         break;
    812     }
    813 
    814     /* Link the new node to it's children */
    815 
    816     PrevChild = NULL;
    817     FirstChild = TRUE;
    818     for (i = 0; i < NumChildren; i++)
    819     {
    820         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
    821 
    822         if ((Child == PrevChild) && (Child != NULL))
    823         {
    824             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
    825                 "Child node list invalid");
    826             va_end(ap);
    827             return (Op);
    828         }
    829 
    830         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
    831 
    832         /*
    833          * If child is NULL, this means that an optional argument
    834          * was omitted. We must create a placeholder with a special
    835          * opcode (DEFAULT_ARG) so that the code generator will know
    836          * that it must emit the correct default for this argument
    837          */
    838         if (!Child)
    839         {
    840             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
    841         }
    842 
    843         /* Link first child to parent */
    844 
    845         if (FirstChild)
    846         {
    847             FirstChild = FALSE;
    848             Op->Asl.Child = Child;
    849         }
    850 
    851         /* Point all children to parent */
    852 
    853         Child->Asl.Parent = Op;
    854 
    855         /* Link children in a peer list */
    856 
    857         if (PrevChild)
    858         {
    859             PrevChild->Asl.Next = Child;
    860         };
    861 
    862         /*
    863          * This child might be a list, point all nodes in the list
    864          * to the same parent
    865          */
    866         while (Child->Asl.Next)
    867         {
    868             Child = Child->Asl.Next;
    869             Child->Asl.Parent = Op;
    870         }
    871         PrevChild = Child;
    872     }
    873 
    874     va_end(ap);
    875     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    876     return (Op);
    877 }
    878 
    879 
    880 /*******************************************************************************
    881  *
    882  * FUNCTION:    TrLinkPeerNode
    883  *
    884  * PARAMETERS:  Op1           - First peer
    885  *              Op2           - Second peer
    886  *
    887  * RETURN:      Op1 or the non-null node.
    888  *
    889  * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
    890  *
    891  ******************************************************************************/
    892 
    893 ACPI_PARSE_OBJECT *
    894 TrLinkPeerNode (
    895     ACPI_PARSE_OBJECT       *Op1,
    896     ACPI_PARSE_OBJECT       *Op2)
    897 {
    898     ACPI_PARSE_OBJECT       *Next;
    899 
    900 
    901     DbgPrint (ASL_PARSE_OUTPUT,
    902         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n",
    903         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
    904         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
    905 
    906 
    907     if ((!Op1) && (!Op2))
    908     {
    909         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
    910         return (Op1);
    911     }
    912 
    913     /* If one of the nodes is null, just return the non-null node */
    914 
    915     if (!Op2)
    916     {
    917         return (Op1);
    918     }
    919 
    920     if (!Op1)
    921     {
    922         return (Op2);
    923     }
    924 
    925     if (Op1 == Op2)
    926     {
    927         DbgPrint (ASL_DEBUG_OUTPUT,
    928             "\n\n************* Internal error, linking node to itself %p\n\n\n",
    929             Op1);
    930         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
    931             "Linking node to itself");
    932         return (Op1);
    933     }
    934 
    935     Op1->Asl.Parent = Op2->Asl.Parent;
    936 
    937     /*
    938      * Op 1 may already have a peer list (such as an IF/ELSE pair),
    939      * so we must walk to the end of the list and attach the new
    940      * peer at the end
    941      */
    942     Next = Op1;
    943     while (Next->Asl.Next)
    944     {
    945         Next = Next->Asl.Next;
    946     }
    947 
    948     Next->Asl.Next = Op2;
    949     return (Op1);
    950 }
    951 
    952 
    953 /*******************************************************************************
    954  *
    955  * FUNCTION:    TrLinkPeerNodes
    956  *
    957  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
    958  *              ...                 - A list of nodes to link together as peers
    959  *
    960  * RETURN:      The first node in the list (head of the peer list)
    961  *
    962  * DESCRIPTION: Link together an arbitrary number of peer nodes.
    963  *
    964  ******************************************************************************/
    965 
    966 ACPI_PARSE_OBJECT *
    967 TrLinkPeerNodes (
    968     UINT32                  NumPeers,
    969     ...)
    970 {
    971     ACPI_PARSE_OBJECT       *This;
    972     ACPI_PARSE_OBJECT       *Next;
    973     va_list                 ap;
    974     UINT32                  i;
    975     ACPI_PARSE_OBJECT       *Start;
    976 
    977 
    978     DbgPrint (ASL_PARSE_OUTPUT,
    979         "\nLinkPeerNodes: (%u) ", NumPeers);
    980 
    981     va_start (ap, NumPeers);
    982     This = va_arg (ap, ACPI_PARSE_OBJECT *);
    983     Start = This;
    984 
    985     /*
    986      * Link all peers
    987      */
    988     for (i = 0; i < (NumPeers -1); i++)
    989     {
    990         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
    991 
    992         while (This->Asl.Next)
    993         {
    994             This = This->Asl.Next;
    995         }
    996 
    997         /* Get another peer node */
    998 
    999         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
   1000         if (!Next)
   1001         {
   1002             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
   1003         }
   1004 
   1005         /* link new node to the current node */
   1006 
   1007         This->Asl.Next = Next;
   1008         This = Next;
   1009     }
   1010     va_end (ap);
   1011 
   1012     DbgPrint (ASL_PARSE_OUTPUT,"\n\n");
   1013     return (Start);
   1014 }
   1015 
   1016 
   1017 /*******************************************************************************
   1018  *
   1019  * FUNCTION:    TrLinkChildNode
   1020  *
   1021  * PARAMETERS:  Op1           - Parent node
   1022  *              Op2           - Op to become a child
   1023  *
   1024  * RETURN:      The parent node
   1025  *
   1026  * DESCRIPTION: Link two nodes together as a parent and child
   1027  *
   1028  ******************************************************************************/
   1029 
   1030 ACPI_PARSE_OBJECT *
   1031 TrLinkChildNode (
   1032     ACPI_PARSE_OBJECT       *Op1,
   1033     ACPI_PARSE_OBJECT       *Op2)
   1034 {
   1035     ACPI_PARSE_OBJECT       *Next;
   1036 
   1037 
   1038     DbgPrint (ASL_PARSE_OUTPUT,
   1039         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n",
   1040         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
   1041         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
   1042 
   1043     if (!Op1 || !Op2)
   1044     {
   1045         return (Op1);
   1046     }
   1047 
   1048     Op1->Asl.Child = Op2;
   1049 
   1050     /* Set the child and all peers of the child to point to the parent */
   1051 
   1052     Next = Op2;
   1053     while (Next)
   1054     {
   1055         Next->Asl.Parent = Op1;
   1056         Next = Next->Asl.Next;
   1057     }
   1058 
   1059     return (Op1);
   1060 }
   1061 
   1062 
   1063 /*******************************************************************************
   1064  *
   1065  * FUNCTION:    TrWalkParseTree
   1066  *
   1067  * PARAMETERS:  Visitation              - Type of walk
   1068  *              DescendingCallback      - Called during tree descent
   1069  *              AscendingCallback       - Called during tree ascent
   1070  *              Context                 - To be passed to the callbacks
   1071  *
   1072  * RETURN:      Status from callback(s)
   1073  *
   1074  * DESCRIPTION: Walk the entire parse tree.
   1075  *
   1076  ******************************************************************************/
   1077 
   1078 ACPI_STATUS
   1079 TrWalkParseTree (
   1080     ACPI_PARSE_OBJECT       *Op,
   1081     UINT32                  Visitation,
   1082     ASL_WALK_CALLBACK       DescendingCallback,
   1083     ASL_WALK_CALLBACK       AscendingCallback,
   1084     void                    *Context)
   1085 {
   1086     UINT32                  Level;
   1087     BOOLEAN                 NodePreviouslyVisited;
   1088     ACPI_PARSE_OBJECT       *StartOp = Op;
   1089     ACPI_STATUS             Status;
   1090 
   1091 
   1092     if (!RootNode)
   1093     {
   1094         return (AE_OK);
   1095     }
   1096 
   1097     Level = 0;
   1098     NodePreviouslyVisited = FALSE;
   1099 
   1100     switch (Visitation)
   1101     {
   1102     case ASL_WALK_VISIT_DOWNWARD:
   1103 
   1104         while (Op)
   1105         {
   1106             if (!NodePreviouslyVisited)
   1107             {
   1108                 /* Let the callback process the node. */
   1109 
   1110                 Status = DescendingCallback (Op, Level, Context);
   1111                 if (ACPI_SUCCESS (Status))
   1112                 {
   1113                     /* Visit children first, once */
   1114 
   1115                     if (Op->Asl.Child)
   1116                     {
   1117                         Level++;
   1118                         Op = Op->Asl.Child;
   1119                         continue;
   1120                     }
   1121                 }
   1122                 else if (Status != AE_CTRL_DEPTH)
   1123                 {
   1124                     /* Exit immediately on any error */
   1125 
   1126                     return (Status);
   1127                 }
   1128             }
   1129 
   1130             /* Terminate walk at start op */
   1131 
   1132             if (Op == StartOp)
   1133             {
   1134                 break;
   1135             }
   1136 
   1137             /* No more children, visit peers */
   1138 
   1139             if (Op->Asl.Next)
   1140             {
   1141                 Op = Op->Asl.Next;
   1142                 NodePreviouslyVisited = FALSE;
   1143             }
   1144             else
   1145             {
   1146                 /* No children or peers, re-visit parent */
   1147 
   1148                 if (Level != 0 )
   1149                 {
   1150                     Level--;
   1151                 }
   1152                 Op = Op->Asl.Parent;
   1153                 NodePreviouslyVisited = TRUE;
   1154             }
   1155         }
   1156         break;
   1157 
   1158     case ASL_WALK_VISIT_UPWARD:
   1159 
   1160         while (Op)
   1161         {
   1162             /* Visit leaf node (no children) or parent node on return trip */
   1163 
   1164             if ((!Op->Asl.Child) ||
   1165                 (NodePreviouslyVisited))
   1166             {
   1167                 /* Let the callback process the node. */
   1168 
   1169                 Status = AscendingCallback (Op, Level, Context);
   1170                 if (ACPI_FAILURE (Status))
   1171                 {
   1172                     return (Status);
   1173                 }
   1174             }
   1175             else
   1176             {
   1177                 /* Visit children first, once */
   1178 
   1179                 Level++;
   1180                 Op = Op->Asl.Child;
   1181                 continue;
   1182             }
   1183 
   1184             /* Terminate walk at start op */
   1185 
   1186             if (Op == StartOp)
   1187             {
   1188                 break;
   1189             }
   1190 
   1191             /* No more children, visit peers */
   1192 
   1193             if (Op->Asl.Next)
   1194             {
   1195                 Op = Op->Asl.Next;
   1196                 NodePreviouslyVisited = FALSE;
   1197             }
   1198             else
   1199             {
   1200                 /* No children or peers, re-visit parent */
   1201 
   1202                 if (Level != 0 )
   1203                 {
   1204                     Level--;
   1205                 }
   1206                 Op = Op->Asl.Parent;
   1207                 NodePreviouslyVisited = TRUE;
   1208             }
   1209         }
   1210         break;
   1211 
   1212      case ASL_WALK_VISIT_TWICE:
   1213 
   1214         while (Op)
   1215         {
   1216             if (NodePreviouslyVisited)
   1217             {
   1218                 Status = AscendingCallback (Op, Level, Context);
   1219                 if (ACPI_FAILURE (Status))
   1220                 {
   1221                     return (Status);
   1222                 }
   1223             }
   1224             else
   1225             {
   1226                 /* Let the callback process the node. */
   1227 
   1228                 Status = DescendingCallback (Op, Level, Context);
   1229                 if (ACPI_SUCCESS (Status))
   1230                 {
   1231                     /* Visit children first, once */
   1232 
   1233                     if (Op->Asl.Child)
   1234                     {
   1235                         Level++;
   1236                         Op = Op->Asl.Child;
   1237                         continue;
   1238                     }
   1239                 }
   1240                 else if (Status != AE_CTRL_DEPTH)
   1241                 {
   1242                     /* Exit immediately on any error */
   1243 
   1244                     return (Status);
   1245                 }
   1246             }
   1247 
   1248             /* Terminate walk at start op */
   1249 
   1250             if (Op == StartOp)
   1251             {
   1252                 break;
   1253             }
   1254 
   1255             /* No more children, visit peers */
   1256 
   1257             if (Op->Asl.Next)
   1258             {
   1259                 Op = Op->Asl.Next;
   1260                 NodePreviouslyVisited = FALSE;
   1261             }
   1262             else
   1263             {
   1264                 /* No children or peers, re-visit parent */
   1265 
   1266                 if (Level != 0 )
   1267                 {
   1268                     Level--;
   1269                 }
   1270                 Op = Op->Asl.Parent;
   1271                 NodePreviouslyVisited = TRUE;
   1272             }
   1273         }
   1274         break;
   1275 
   1276     default:
   1277         /* No other types supported */
   1278         break;
   1279     }
   1280 
   1281     /* If we get here, the walk completed with no errors */
   1282 
   1283     return (AE_OK);
   1284 }
   1285