asltree.c revision 123315
1118611Snjl 2118611Snjl/****************************************************************************** 3118611Snjl * 4118611Snjl * Module Name: asltree - parse tree management 5123315Snjl * $Revision: 54 $ 6118611Snjl * 7118611Snjl *****************************************************************************/ 8118611Snjl 9118611Snjl/****************************************************************************** 10118611Snjl * 11118611Snjl * 1. Copyright Notice 12118611Snjl * 13118611Snjl * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp. 14118611Snjl * All rights reserved. 15118611Snjl * 16118611Snjl * 2. License 17118611Snjl * 18118611Snjl * 2.1. This is your license from Intel Corp. under its intellectual property 19118611Snjl * rights. You may have additional license terms from the party that provided 20118611Snjl * you this software, covering your right to use that party's intellectual 21118611Snjl * property rights. 22118611Snjl * 23118611Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24118611Snjl * copy of the source code appearing in this file ("Covered Code") an 25118611Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26118611Snjl * base code distributed originally by Intel ("Original Intel Code") to copy, 27118611Snjl * make derivatives, distribute, use and display any portion of the Covered 28118611Snjl * Code in any form, with the right to sublicense such rights; and 29118611Snjl * 30118611Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31118611Snjl * license (with the right to sublicense), under only those claims of Intel 32118611Snjl * patents that are infringed by the Original Intel Code, to make, use, sell, 33118611Snjl * offer to sell, and import the Covered Code and derivative works thereof 34118611Snjl * solely to the minimum extent necessary to exercise the above copyright 35118611Snjl * license, and in no event shall the patent license extend to any additions 36118611Snjl * to or modifications of the Original Intel Code. No other license or right 37118611Snjl * is granted directly or by implication, estoppel or otherwise; 38118611Snjl * 39118611Snjl * The above copyright and patent license is granted only if the following 40118611Snjl * conditions are met: 41118611Snjl * 42118611Snjl * 3. Conditions 43118611Snjl * 44118611Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45118611Snjl * Redistribution of source code of any substantial portion of the Covered 46118611Snjl * Code or modification with rights to further distribute source must include 47118611Snjl * the above Copyright Notice, the above License, this list of Conditions, 48118611Snjl * and the following Disclaimer and Export Compliance provision. In addition, 49118611Snjl * Licensee must cause all Covered Code to which Licensee contributes to 50118611Snjl * contain a file documenting the changes Licensee made to create that Covered 51118611Snjl * Code and the date of any change. Licensee must include in that file the 52118611Snjl * documentation of any changes made by any predecessor Licensee. Licensee 53118611Snjl * must include a prominent statement that the modification is derived, 54118611Snjl * directly or indirectly, from Original Intel Code. 55118611Snjl * 56118611Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57118611Snjl * Redistribution of source code of any substantial portion of the Covered 58118611Snjl * Code or modification without rights to further distribute source must 59118611Snjl * include the following Disclaimer and Export Compliance provision in the 60118611Snjl * documentation and/or other materials provided with distribution. In 61118611Snjl * addition, Licensee may not authorize further sublicense of source of any 62118611Snjl * portion of the Covered Code, and must include terms to the effect that the 63118611Snjl * license from Licensee to its licensee is limited to the intellectual 64118611Snjl * property embodied in the software Licensee provides to its licensee, and 65118611Snjl * not to intellectual property embodied in modifications its licensee may 66118611Snjl * make. 67118611Snjl * 68118611Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any 69118611Snjl * substantial portion of the Covered Code or modification must reproduce the 70118611Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance 71118611Snjl * provision in the documentation and/or other materials provided with the 72118611Snjl * distribution. 73118611Snjl * 74118611Snjl * 3.4. Intel retains all right, title, and interest in and to the Original 75118611Snjl * Intel Code. 76118611Snjl * 77118611Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78118611Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or 79118611Snjl * other dealings in products derived from or relating to the Covered Code 80118611Snjl * without prior written authorization from Intel. 81118611Snjl * 82118611Snjl * 4. Disclaimer and Export Compliance 83118611Snjl * 84118611Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85118611Snjl * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86118611Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87118611Snjl * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88118611Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89118611Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90118611Snjl * PARTICULAR PURPOSE. 91118611Snjl * 92118611Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93118611Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94118611Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95118611Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96118611Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97118611Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98118611Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99118611Snjl * LIMITED REMEDY. 100118611Snjl * 101118611Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this 102118611Snjl * software or system incorporating such software without first obtaining any 103118611Snjl * required license or other approval from the U. S. Department of Commerce or 104118611Snjl * any other agency or department of the United States Government. In the 105118611Snjl * event Licensee exports any such software from the United States or 106118611Snjl * re-exports any such software from a foreign destination, Licensee shall 107118611Snjl * ensure that the distribution and export/re-export of the software is in 108118611Snjl * compliance with all laws, regulations, orders, or other restrictions of the 109118611Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110118611Snjl * any of its subsidiaries will export/re-export any technical data, process, 111118611Snjl * software, or service, directly or indirectly, to any country for which the 112118611Snjl * United States government or any agency thereof requires an export license, 113118611Snjl * other governmental approval, or letter of assurance, without first obtaining 114118611Snjl * such license, approval or letter. 115118611Snjl * 116118611Snjl *****************************************************************************/ 117118611Snjl 118118611Snjl 119118611Snjl#include "aslcompiler.h" 120118611Snjl#include "aslcompiler.y.h" 121118611Snjl 122118611Snjl#define _COMPONENT ACPI_COMPILER 123118611Snjl ACPI_MODULE_NAME ("asltree") 124118611Snjl 125118611Snjl 126118611Snjl/******************************************************************************* 127118611Snjl * 128118611Snjl * FUNCTION: TrGetNextNode 129118611Snjl * 130118611Snjl * PARAMETERS: None 131118611Snjl * 132118611Snjl * RETURN: New parse node. Aborts on allocation failure 133118611Snjl * 134118611Snjl * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 135118611Snjl * dynamic memory manager for performance reasons (This has a 136118611Snjl * major impact on the speed of the compiler.) 137118611Snjl * 138118611Snjl ******************************************************************************/ 139118611Snjl 140118611SnjlACPI_PARSE_OBJECT * 141118611SnjlTrGetNextNode (void) 142118611Snjl{ 143118611Snjl 144118611Snjl if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast) 145118611Snjl { 146118611Snjl Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) * ASL_NODE_CACHE_SIZE); 147118611Snjl Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE; 148118611Snjl } 149118611Snjl 150118611Snjl return (Gbl_NodeCacheNext++); 151118611Snjl} 152118611Snjl 153118611Snjl 154118611Snjl/******************************************************************************* 155118611Snjl * 156118611Snjl * FUNCTION: TrAllocateNode 157118611Snjl * 158118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 159118611Snjl * 160118611Snjl * RETURN: New parse node. Aborts on allocation failure 161118611Snjl * 162118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 163118611Snjl * 164118611Snjl ******************************************************************************/ 165118611Snjl 166118611SnjlACPI_PARSE_OBJECT * 167118611SnjlTrAllocateNode ( 168118611Snjl UINT32 ParseOpcode) 169118611Snjl{ 170118611Snjl ACPI_PARSE_OBJECT *Op; 171118611Snjl 172118611Snjl 173118611Snjl Op = TrGetNextNode (); 174118611Snjl 175118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 176118611Snjl Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 177118611Snjl Op->Asl.LineNumber = Gbl_CurrentLineNumber; 178118611Snjl Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 179118611Snjl Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 180118611Snjl Op->Asl.Column = Gbl_CurrentColumn; 181118611Snjl 182118611Snjl UtSetParseOpName (Op); 183118611Snjl return Op; 184118611Snjl} 185118611Snjl 186118611Snjl 187118611Snjl/******************************************************************************* 188118611Snjl * 189118611Snjl * FUNCTION: TrReleaseNode 190118611Snjl * 191118611Snjl * PARAMETERS: Op - Op to be released 192118611Snjl * 193118611Snjl * RETURN: None 194118611Snjl * 195118611Snjl * DESCRIPTION: "release" a node. In truth, nothing is done since the node 196118611Snjl * is part of a larger buffer 197118611Snjl * 198118611Snjl ******************************************************************************/ 199118611Snjl 200118611Snjlvoid 201118611SnjlTrReleaseNode ( 202118611Snjl ACPI_PARSE_OBJECT *Op) 203118611Snjl{ 204118611Snjl 205118611Snjl return; 206118611Snjl} 207118611Snjl 208118611Snjl 209118611Snjl/******************************************************************************* 210118611Snjl * 211118611Snjl * FUNCTION: TrUpdateNode 212118611Snjl * 213118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 214118611Snjl * Op - An existing parse node 215118611Snjl * 216118611Snjl * RETURN: The updated node 217118611Snjl * 218118611Snjl * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 219118611Snjl * change an opcode to DEFAULT_ARG so that the node is ignored 220118611Snjl * during the code generation. Also used to set generic integers 221118611Snjl * to a specific size (8, 16, 32, or 64 bits) 222118611Snjl * 223118611Snjl ******************************************************************************/ 224118611Snjl 225118611SnjlACPI_PARSE_OBJECT * 226118611SnjlTrUpdateNode ( 227118611Snjl UINT32 ParseOpcode, 228118611Snjl ACPI_PARSE_OBJECT *Op) 229118611Snjl{ 230118611Snjl 231118611Snjl if (!Op) 232118611Snjl { 233118611Snjl return NULL; 234118611Snjl } 235118611Snjl 236118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 237118611Snjl "\nUpdateNode: Old - %s, New - %s\n\n", 238118611Snjl UtGetOpName (Op->Asl.ParseOpcode), 239118611Snjl UtGetOpName (ParseOpcode)); 240118611Snjl 241118611Snjl /* Assign new opcode and name */ 242118611Snjl 243118611Snjl if (Op->Asl.ParseOpcode == PARSEOP_ONES) 244118611Snjl { 245118611Snjl switch (ParseOpcode) 246118611Snjl { 247118611Snjl case PARSEOP_BYTECONST: 248118611Snjl Op->Asl.Value.Integer = 0xFF; 249118611Snjl break; 250118611Snjl 251118611Snjl case PARSEOP_WORDCONST: 252118611Snjl Op->Asl.Value.Integer = 0xFFFF; 253118611Snjl break; 254118611Snjl 255118611Snjl case PARSEOP_DWORDCONST: 256118611Snjl Op->Asl.Value.Integer = 0xFFFFFFFF; 257118611Snjl break; 258118611Snjl 259118611Snjl default: 260118611Snjl /* Don't care about others, don't need to check QWORD */ 261118611Snjl break; 262118611Snjl } 263118611Snjl } 264118611Snjl 265118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 266118611Snjl UtSetParseOpName (Op); 267118611Snjl 268118611Snjl /* 269118611Snjl * For the BYTE, WORD, and DWORD constants, make sure that the integer 270118611Snjl * that was passed in will actually fit into the data type 271118611Snjl */ 272118611Snjl switch (ParseOpcode) 273118611Snjl { 274118611Snjl case PARSEOP_BYTECONST: 275118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 276118611Snjl break; 277118611Snjl 278118611Snjl case PARSEOP_WORDCONST: 279118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 280118611Snjl break; 281118611Snjl 282118611Snjl case PARSEOP_DWORDCONST: 283118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 284118611Snjl break; 285118611Snjl 286118611Snjl default: 287118611Snjl /* Don't care about others, don't need to check QWORD */ 288118611Snjl break; 289118611Snjl } 290118611Snjl 291118611Snjl return Op; 292118611Snjl} 293118611Snjl 294118611Snjl 295118611Snjl/******************************************************************************* 296118611Snjl * 297118611Snjl * FUNCTION: TrGetNodeFlagName 298118611Snjl * 299118611Snjl * PARAMETERS: Flags - Flags word to be decoded 300118611Snjl * 301118611Snjl * RETURN: Name string 302118611Snjl * 303118611Snjl * DESCRIPTION: Decode a flags word 304118611Snjl * 305118611Snjl ******************************************************************************/ 306118611Snjl 307118611Snjlchar * 308118611SnjlTrGetNodeFlagName ( 309118611Snjl UINT32 Flags) 310118611Snjl{ 311118611Snjl 312118611Snjl switch (Flags) 313118611Snjl { 314118611Snjl case NODE_VISITED: 315118611Snjl return ("NODE_VISITED"); 316118611Snjl 317118611Snjl case NODE_AML_PACKAGE: 318118611Snjl return ("NODE_AML_PACKAGE"); 319118611Snjl 320118611Snjl case NODE_IS_TARGET: 321118611Snjl return ("NODE_IS_TARGET"); 322118611Snjl 323118611Snjl case NODE_IS_RESOURCE_DESC: 324118611Snjl return ("NODE_IS_RESOURCE_DESC"); 325118611Snjl 326118611Snjl case NODE_IS_RESOURCE_FIELD: 327118611Snjl return ("NODE_IS_RESOURCE_FIELD"); 328118611Snjl 329118611Snjl case NODE_HAS_NO_EXIT: 330118611Snjl return ("NODE_HAS_NO_EXIT"); 331118611Snjl 332118611Snjl case NODE_IF_HAS_NO_EXIT: 333118611Snjl return ("NODE_IF_HAS_NO_EXIT"); 334118611Snjl 335118611Snjl case NODE_NAME_INTERNALIZED: 336118611Snjl return ("NODE_NAME_INTERNALIZED"); 337118611Snjl 338118611Snjl case NODE_METHOD_NO_RETVAL: 339118611Snjl return ("NODE_METHOD_NO_RETVAL"); 340118611Snjl 341118611Snjl case NODE_METHOD_SOME_NO_RETVAL: 342118611Snjl return ("NODE_METHOD_SOME_NO_RETVAL"); 343118611Snjl 344118611Snjl case NODE_RESULT_NOT_USED: 345118611Snjl return ("NODE_RESULT_NOT_USED"); 346118611Snjl 347118611Snjl case NODE_METHOD_TYPED: 348118611Snjl return ("NODE_METHOD_TYPED"); 349118611Snjl 350118611Snjl case NODE_IS_BIT_OFFSET: 351118611Snjl return ("NODE_IS_BIT_OFFSET"); 352118611Snjl 353118611Snjl case NODE_COMPILE_TIME_CONST: 354118611Snjl return ("NODE_COMPILE_TIME_CONST"); 355118611Snjl 356118611Snjl case NODE_IS_TERM_ARG: 357118611Snjl return ("NODE_IS_TERM_ARG"); 358118611Snjl 359118611Snjl case NODE_WAS_ONES_OP: 360118611Snjl return ("NODE_WAS_ONES_OP"); 361118611Snjl 362118611Snjl case NODE_IS_NAME_DECLARATION: 363118611Snjl return ("NODE_IS_NAME_DECLARATION"); 364118611Snjl 365118611Snjl default: 366118611Snjl return ("Multiple Flags (or unknown flag) set"); 367118611Snjl } 368118611Snjl} 369118611Snjl 370118611Snjl 371118611Snjl/******************************************************************************* 372118611Snjl * 373118611Snjl * FUNCTION: TrSetNodeFlags 374118611Snjl * 375118611Snjl * PARAMETERS: Op - An existing parse node 376118611Snjl * Flags - New flags word 377118611Snjl * 378118611Snjl * RETURN: The updated node 379118611Snjl * 380118611Snjl * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 381118611Snjl * 382118611Snjl ******************************************************************************/ 383118611Snjl 384118611SnjlACPI_PARSE_OBJECT * 385118611SnjlTrSetNodeFlags ( 386118611Snjl ACPI_PARSE_OBJECT *Op, 387118611Snjl UINT32 Flags) 388118611Snjl{ 389118611Snjl 390118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 391118611Snjl "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags, TrGetNodeFlagName (Flags)); 392118611Snjl 393118611Snjl if (!Op) 394118611Snjl { 395118611Snjl return NULL; 396118611Snjl } 397118611Snjl 398118611Snjl Op->Asl.CompileFlags |= Flags; 399118611Snjl 400118611Snjl return Op; 401118611Snjl} 402118611Snjl 403118611Snjl 404118611Snjl/******************************************************************************* 405118611Snjl * 406118611Snjl * FUNCTION: TrSetEndLineNumber 407118611Snjl * 408118611Snjl * PARAMETERS: Op - An existing parse node 409118611Snjl * 410118611Snjl * RETURN: None. 411118611Snjl * 412118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 413118611Snjl * parse node to the current line numbers. 414118611Snjl * 415118611Snjl ******************************************************************************/ 416118611Snjl 417118611Snjlvoid 418118611SnjlTrSetEndLineNumber ( 419118611Snjl ACPI_PARSE_OBJECT *Op) 420118611Snjl{ 421118611Snjl 422118611Snjl /* If the end line # is already set, just return */ 423118611Snjl 424118611Snjl if (Op->Asl.EndLine) 425118611Snjl { 426118611Snjl return; 427118611Snjl } 428118611Snjl 429118611Snjl Op->Asl.EndLine = Gbl_CurrentLineNumber; 430118611Snjl Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 431118611Snjl} 432118611Snjl 433118611Snjl 434118611Snjl/******************************************************************************* 435118611Snjl * 436118611Snjl * FUNCTION: TrCreateLeafNode 437118611Snjl * 438118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 439118611Snjl * 440118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 441118611Snjl * 442118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 443118611Snjl * assigned to the node) 444118611Snjl * 445118611Snjl ******************************************************************************/ 446118611Snjl 447118611SnjlACPI_PARSE_OBJECT * 448118611SnjlTrCreateLeafNode ( 449118611Snjl UINT32 ParseOpcode) 450118611Snjl{ 451118611Snjl ACPI_PARSE_OBJECT *Op; 452118611Snjl 453118611Snjl 454118611Snjl Op = TrAllocateNode (ParseOpcode); 455118611Snjl 456118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 457118611Snjl "\nCreateLeafNode Line %d NewNode %p Op %s\n\n", 458118611Snjl Op->Asl.LineNumber, Op, UtGetOpName(ParseOpcode)); 459118611Snjl 460118611Snjl return Op; 461118611Snjl} 462118611Snjl 463118611Snjl 464118611Snjl/******************************************************************************* 465118611Snjl * 466118611Snjl * FUNCTION: TrCreateValuedLeafNode 467118611Snjl * 468118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 469118611Snjl * Value - Value to be assigned to the node 470118611Snjl * 471118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 472118611Snjl * 473118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value 474118611Snjl * assigned to it 475118611Snjl * 476118611Snjl ******************************************************************************/ 477118611Snjl 478118611SnjlACPI_PARSE_OBJECT * 479118611SnjlTrCreateValuedLeafNode ( 480118611Snjl UINT32 ParseOpcode, 481118611Snjl ACPI_INTEGER Value) 482118611Snjl{ 483118611Snjl ACPI_PARSE_OBJECT *Op; 484118611Snjl 485118611Snjl 486118611Snjl Op = TrAllocateNode (ParseOpcode); 487118611Snjl 488118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 489118611Snjl "\nCreateValuedLeafNode Line %d NewNode %p Op %s Value %8.8X%8.8X ", 490118611Snjl Op->Asl.LineNumber, Op, UtGetOpName(ParseOpcode), 491123315Snjl ACPI_FORMAT_UINT64 (Value)); 492118611Snjl Op->Asl.Value.Integer = Value; 493118611Snjl 494118611Snjl switch (ParseOpcode) 495118611Snjl { 496118611Snjl case PARSEOP_STRING_LITERAL: 497118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 498118611Snjl break; 499118611Snjl 500118611Snjl case PARSEOP_NAMESEG: 501118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 502118611Snjl break; 503118611Snjl 504118611Snjl case PARSEOP_NAMESTRING: 505118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 506118611Snjl break; 507118611Snjl 508118611Snjl case PARSEOP_EISAID: 509118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 510118611Snjl break; 511118611Snjl 512118611Snjl case PARSEOP_METHOD: 513118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 514118611Snjl break; 515118611Snjl 516118611Snjl case PARSEOP_INTEGER: 517118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "INTEGER"); 518118611Snjl break; 519118611Snjl 520118611Snjl default: 521118611Snjl break; 522118611Snjl } 523118611Snjl 524118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 525118611Snjl return Op; 526118611Snjl} 527118611Snjl 528118611Snjl 529118611Snjl/******************************************************************************* 530118611Snjl * 531118611Snjl * FUNCTION: TrCreateNode 532118611Snjl * 533118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 534118611Snjl * NumChildren - Number of children to follow 535118611Snjl * ... - A list of child nodes to link to the new 536118611Snjl * node. NumChildren long. 537118611Snjl * 538118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 539118611Snjl * 540118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child 541118611Snjl * nodes underneath the new node. 542118611Snjl * 543118611Snjl ******************************************************************************/ 544118611Snjl 545118611SnjlACPI_PARSE_OBJECT * 546118611SnjlTrCreateNode ( 547118611Snjl UINT32 ParseOpcode, 548118611Snjl UINT32 NumChildren, 549118611Snjl ...) 550118611Snjl{ 551118611Snjl ACPI_PARSE_OBJECT *Op; 552118611Snjl ACPI_PARSE_OBJECT *Child; 553118611Snjl ACPI_PARSE_OBJECT *PrevChild; 554118611Snjl va_list ap; 555118611Snjl UINT32 i; 556118611Snjl BOOLEAN FirstChild; 557118611Snjl 558118611Snjl 559118611Snjl va_start (ap, NumChildren); 560118611Snjl 561118611Snjl /* Allocate one new node */ 562118611Snjl 563118611Snjl Op = TrAllocateNode (ParseOpcode); 564118611Snjl 565118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 566118611Snjl "\nCreateNode Line %d NewParent %p Child %d Op %s ", 567118611Snjl Op->Asl.LineNumber, Op, NumChildren, UtGetOpName(ParseOpcode)); 568118611Snjl 569118611Snjl /* Some extra debug output based on the parse opcode */ 570118611Snjl 571118611Snjl switch (ParseOpcode) 572118611Snjl { 573118611Snjl case PARSEOP_DEFINITIONBLOCK: 574118611Snjl RootNode = Op; 575118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 576118611Snjl break; 577118611Snjl 578118611Snjl case PARSEOP_OPERATIONREGION: 579118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 580118611Snjl break; 581118611Snjl 582118611Snjl case PARSEOP_OR: 583118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 584118611Snjl break; 585118611Snjl 586118611Snjl default: 587118611Snjl /* Nothing to do for other opcodes */ 588118611Snjl break; 589118611Snjl } 590118611Snjl 591118611Snjl /* Link the new node to its children */ 592118611Snjl 593118611Snjl PrevChild = NULL; 594118611Snjl FirstChild = TRUE; 595118611Snjl for (i = 0; i < NumChildren; i++) 596118611Snjl { 597118611Snjl /* Get the next child */ 598118611Snjl 599118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 600118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 601118611Snjl 602118611Snjl /* 603118611Snjl * If child is NULL, this means that an optional argument 604118611Snjl * was omitted. We must create a placeholder with a special 605118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 606118611Snjl * that it must emit the correct default for this argument 607118611Snjl */ 608118611Snjl if (!Child) 609118611Snjl { 610118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 611118611Snjl } 612118611Snjl 613118611Snjl /* Link first child to parent */ 614118611Snjl 615118611Snjl if (FirstChild) 616118611Snjl { 617118611Snjl FirstChild = FALSE; 618118611Snjl Op->Asl.Child = Child; 619118611Snjl } 620118611Snjl 621118611Snjl /* Point all children to parent */ 622118611Snjl 623118611Snjl Child->Asl.Parent = Op; 624118611Snjl 625118611Snjl /* Link children in a peer list */ 626118611Snjl 627118611Snjl if (PrevChild) 628118611Snjl { 629118611Snjl PrevChild->Asl.Next = Child; 630118611Snjl }; 631118611Snjl 632118611Snjl /* 633118611Snjl * This child might be a list, point all nodes in the list 634118611Snjl * to the same parent 635118611Snjl */ 636118611Snjl while (Child->Asl.Next) 637118611Snjl { 638118611Snjl Child = Child->Asl.Next; 639118611Snjl Child->Asl.Parent = Op; 640118611Snjl } 641118611Snjl 642118611Snjl PrevChild = Child; 643118611Snjl } 644118611Snjl va_end(ap); 645118611Snjl 646118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 647118611Snjl return Op; 648118611Snjl} 649118611Snjl 650118611Snjl 651118611Snjl/******************************************************************************* 652118611Snjl * 653118611Snjl * FUNCTION: TrLinkChildren 654118611Snjl * 655118611Snjl * PARAMETERS: Op - An existing parse node 656118611Snjl * NumChildren - Number of children to follow 657118611Snjl * ... - A list of child nodes to link to the new 658118611Snjl * node. NumChildren long. 659118611Snjl * 660118611Snjl * RETURN: The updated (linked) node 661118611Snjl * 662118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node 663118611Snjl * 664118611Snjl ******************************************************************************/ 665118611Snjl 666118611SnjlACPI_PARSE_OBJECT * 667118611SnjlTrLinkChildren ( 668118611Snjl ACPI_PARSE_OBJECT *Op, 669118611Snjl UINT32 NumChildren, 670118611Snjl ...) 671118611Snjl{ 672118611Snjl ACPI_PARSE_OBJECT *Child; 673118611Snjl ACPI_PARSE_OBJECT *PrevChild; 674118611Snjl va_list ap; 675118611Snjl UINT32 i; 676118611Snjl BOOLEAN FirstChild; 677118611Snjl 678118611Snjl 679118611Snjl va_start (ap, NumChildren); 680118611Snjl 681118611Snjl 682118611Snjl TrSetEndLineNumber (Op); 683118611Snjl 684118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 685118611Snjl "\nLinkChildren Line [%d to %d] NewParent %p Child %d Op %s ", 686118611Snjl Op->Asl.LineNumber, Op->Asl.EndLine, 687118611Snjl Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 688118611Snjl 689118611Snjl switch (Op->Asl.ParseOpcode) 690118611Snjl { 691118611Snjl case PARSEOP_DEFINITIONBLOCK: 692118611Snjl RootNode = Op; 693118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 694118611Snjl break; 695118611Snjl 696118611Snjl case PARSEOP_OPERATIONREGION: 697118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 698118611Snjl break; 699118611Snjl 700118611Snjl case PARSEOP_OR: 701118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 702118611Snjl break; 703118611Snjl 704118611Snjl default: 705118611Snjl /* Nothing to do for other opcodes */ 706118611Snjl break; 707118611Snjl } 708118611Snjl 709118611Snjl /* Link the new node to it's children */ 710118611Snjl 711118611Snjl PrevChild = NULL; 712118611Snjl FirstChild = TRUE; 713118611Snjl for (i = 0; i < NumChildren; i++) 714118611Snjl { 715118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 716118611Snjl 717118611Snjl if ((Child == PrevChild) && (Child != NULL)) 718118611Snjl { 719118611Snjl AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, "Child node list invalid"); 720118611Snjl return Op; 721118611Snjl } 722118611Snjl 723118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 724118611Snjl 725118611Snjl /* 726118611Snjl * If child is NULL, this means that an optional argument 727118611Snjl * was omitted. We must create a placeholder with a special 728118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 729118611Snjl * that it must emit the correct default for this argument 730118611Snjl */ 731118611Snjl if (!Child) 732118611Snjl { 733118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 734118611Snjl } 735118611Snjl 736118611Snjl /* Link first child to parent */ 737118611Snjl 738118611Snjl if (FirstChild) 739118611Snjl { 740118611Snjl FirstChild = FALSE; 741118611Snjl Op->Asl.Child = Child; 742118611Snjl } 743118611Snjl 744118611Snjl /* Point all children to parent */ 745118611Snjl 746118611Snjl Child->Asl.Parent = Op; 747118611Snjl 748118611Snjl /* Link children in a peer list */ 749118611Snjl 750118611Snjl if (PrevChild) 751118611Snjl { 752118611Snjl PrevChild->Asl.Next = Child; 753118611Snjl }; 754118611Snjl 755118611Snjl /* 756118611Snjl * This child might be a list, point all nodes in the list 757118611Snjl * to the same parent 758118611Snjl */ 759118611Snjl while (Child->Asl.Next) 760118611Snjl { 761118611Snjl Child = Child->Asl.Next; 762118611Snjl Child->Asl.Parent = Op; 763118611Snjl } 764118611Snjl PrevChild = Child; 765118611Snjl } 766118611Snjl va_end(ap); 767118611Snjl 768118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 769118611Snjl return Op; 770118611Snjl} 771118611Snjl 772118611Snjl 773118611Snjl/******************************************************************************* 774118611Snjl * 775118611Snjl * FUNCTION: TrLinkPeerNode 776118611Snjl * 777118611Snjl * PARAMETERS: Op1 - First peer 778118611Snjl * Op2 - Second peer 779118611Snjl * 780118611Snjl * RETURN: Op1 or the non-null node. 781118611Snjl * 782118611Snjl * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 783118611Snjl * 784118611Snjl ******************************************************************************/ 785118611Snjl 786118611SnjlACPI_PARSE_OBJECT * 787118611SnjlTrLinkPeerNode ( 788118611Snjl ACPI_PARSE_OBJECT *Op1, 789118611Snjl ACPI_PARSE_OBJECT *Op2) 790118611Snjl{ 791118611Snjl ACPI_PARSE_OBJECT *Next; 792118611Snjl 793118611Snjl 794118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 795118611Snjl "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n", 796118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 797118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 798118611Snjl 799118611Snjl 800118611Snjl if ((!Op1) && (!Op2)) 801118611Snjl { 802118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 803118611Snjl return Op1; 804118611Snjl } 805118611Snjl 806118611Snjl /* If one of the nodes is null, just return the non-null node */ 807118611Snjl 808118611Snjl if (!Op2) 809118611Snjl { 810118611Snjl return Op1; 811118611Snjl } 812118611Snjl 813118611Snjl if (!Op1) 814118611Snjl { 815118611Snjl return Op2; 816118611Snjl } 817118611Snjl 818118611Snjl if (Op1 == Op2) 819118611Snjl { 820118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 821118611Snjl "\n\n************* Internal error, linking node to itself %p\n\n\n", Op1); 822118611Snjl AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, "Linking node to itself"); 823118611Snjl return Op1; 824118611Snjl } 825118611Snjl 826118611Snjl Op1->Asl.Parent = Op2->Asl.Parent; 827118611Snjl 828118611Snjl /* 829118611Snjl * Op 1 may already have a peer list (such as an IF/ELSE pair), 830118611Snjl * so we must walk to the end of the list and attach the new 831118611Snjl * peer at the end 832118611Snjl */ 833118611Snjl Next = Op1; 834118611Snjl while (Next->Asl.Next) 835118611Snjl { 836118611Snjl Next = Next->Asl.Next; 837118611Snjl } 838118611Snjl 839118611Snjl Next->Asl.Next = Op2; 840118611Snjl return Op1; 841118611Snjl} 842118611Snjl 843118611Snjl 844118611Snjl/******************************************************************************* 845118611Snjl * 846118611Snjl * FUNCTION: TrLinkPeerNodes 847118611Snjl * 848118611Snjl * PARAMETERS: NumPeers - The number of nodes in the list to follow 849118611Snjl * ... - A list of nodes to link together as peers 850118611Snjl * 851118611Snjl * RETURN: The first node in the list (head of the peer list) 852118611Snjl * 853118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes. 854118611Snjl * 855118611Snjl ******************************************************************************/ 856118611Snjl 857118611SnjlACPI_PARSE_OBJECT * 858118611SnjlTrLinkPeerNodes ( 859118611Snjl UINT32 NumPeers, 860118611Snjl ...) 861118611Snjl{ 862118611Snjl ACPI_PARSE_OBJECT *This; 863118611Snjl ACPI_PARSE_OBJECT *Next; 864118611Snjl va_list ap; 865118611Snjl UINT32 i; 866118611Snjl ACPI_PARSE_OBJECT *Start; 867118611Snjl 868118611Snjl 869118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 870118611Snjl "\nLinkPeerNodes: (%d) ", NumPeers); 871118611Snjl 872118611Snjl va_start (ap, NumPeers); 873118611Snjl This = va_arg (ap, ACPI_PARSE_OBJECT *); 874118611Snjl Start = This; 875118611Snjl 876118611Snjl /* 877118611Snjl * Link all peers 878118611Snjl */ 879118611Snjl for (i = 0; i < (NumPeers -1); i++) 880118611Snjl { 881118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%d=%p ", (i+1), This); 882118611Snjl 883118611Snjl while (This->Asl.Next) 884118611Snjl { 885118611Snjl This = This->Asl.Next; 886118611Snjl } 887118611Snjl 888118611Snjl /* Get another peer node */ 889118611Snjl 890118611Snjl Next = va_arg (ap, ACPI_PARSE_OBJECT *); 891118611Snjl if (!Next) 892118611Snjl { 893118611Snjl Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 894118611Snjl } 895118611Snjl 896118611Snjl /* link new node to the current node */ 897118611Snjl 898118611Snjl This->Asl.Next = Next; 899118611Snjl This = Next; 900118611Snjl } 901118611Snjl 902118611Snjl DbgPrint (ASL_PARSE_OUTPUT,"\n\n"); 903118611Snjl return (Start); 904118611Snjl} 905118611Snjl 906118611Snjl 907118611Snjl/******************************************************************************* 908118611Snjl * 909118611Snjl * FUNCTION: TrLinkChildNode 910118611Snjl * 911118611Snjl * PARAMETERS: Op1 - Parent node 912118611Snjl * Op2 - Op to become a child 913118611Snjl * 914118611Snjl * RETURN: The parent node 915118611Snjl * 916118611Snjl * DESCRIPTION: Link two nodes together as a parent and child 917118611Snjl * 918118611Snjl ******************************************************************************/ 919118611Snjl 920118611SnjlACPI_PARSE_OBJECT * 921118611SnjlTrLinkChildNode ( 922118611Snjl ACPI_PARSE_OBJECT *Op1, 923118611Snjl ACPI_PARSE_OBJECT *Op2) 924118611Snjl{ 925118611Snjl ACPI_PARSE_OBJECT *Next; 926118611Snjl 927118611Snjl 928118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 929118611Snjl "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n", 930118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 931118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 932118611Snjl 933118611Snjl if (!Op1 || !Op2) 934118611Snjl { 935118611Snjl return Op1; 936118611Snjl } 937118611Snjl 938118611Snjl Op1->Asl.Child = Op2; 939118611Snjl 940118611Snjl /* Set the child and all peers of the child to point to the parent */ 941118611Snjl 942118611Snjl Next = Op2; 943118611Snjl while (Next) 944118611Snjl { 945118611Snjl Next->Asl.Parent = Op1; 946118611Snjl Next = Next->Asl.Next; 947118611Snjl } 948118611Snjl 949118611Snjl return Op1; 950118611Snjl} 951118611Snjl 952118611Snjl 953118611Snjl/******************************************************************************* 954118611Snjl * 955118611Snjl * FUNCTION: TrWalkParseTree 956118611Snjl * 957118611Snjl * PARAMETERS: Visitation - Type of walk 958118611Snjl * DescendingCallback - Called during tree descent 959118611Snjl * AscendingCallback - Called during tree ascent 960118611Snjl * Context - To be passed to the callbacks 961118611Snjl * 962118611Snjl * RETURN: Status from callback(s) 963118611Snjl * 964118611Snjl * DESCRIPTION: Walk the entire parse tree. 965118611Snjl * 966118611Snjl ******************************************************************************/ 967118611Snjl 968118611SnjlACPI_STATUS 969118611SnjlTrWalkParseTree ( 970118611Snjl ACPI_PARSE_OBJECT *Op, 971118611Snjl UINT32 Visitation, 972118611Snjl ASL_WALK_CALLBACK DescendingCallback, 973118611Snjl ASL_WALK_CALLBACK AscendingCallback, 974118611Snjl void *Context) 975118611Snjl{ 976118611Snjl UINT32 Level; 977118611Snjl BOOLEAN NodePreviouslyVisited; 978118611Snjl ACPI_PARSE_OBJECT *StartOp = Op; 979118611Snjl ACPI_STATUS Status; 980118611Snjl 981118611Snjl 982118611Snjl if (!RootNode) 983118611Snjl { 984118611Snjl return (AE_OK); 985118611Snjl } 986118611Snjl 987118611Snjl Level = 0; 988118611Snjl NodePreviouslyVisited = FALSE; 989118611Snjl 990118611Snjl switch (Visitation) 991118611Snjl { 992118611Snjl case ASL_WALK_VISIT_DOWNWARD: 993118611Snjl 994118611Snjl while (Op) 995118611Snjl { 996118611Snjl if (!NodePreviouslyVisited) 997118611Snjl { 998118611Snjl /* 999118611Snjl * Let the callback process the node. 1000118611Snjl */ 1001118611Snjl Status = DescendingCallback (Op, Level, Context); 1002118611Snjl if (ACPI_SUCCESS (Status)) 1003118611Snjl { 1004118611Snjl /* Visit children first, once */ 1005118611Snjl 1006118611Snjl if (Op->Asl.Child) 1007118611Snjl { 1008118611Snjl Level++; 1009118611Snjl Op = Op->Asl.Child; 1010118611Snjl continue; 1011118611Snjl } 1012118611Snjl } 1013118611Snjl else if (Status != AE_CTRL_DEPTH) 1014118611Snjl { 1015118611Snjl /* Exit immediately on any error */ 1016118611Snjl 1017118611Snjl return (Status); 1018118611Snjl } 1019118611Snjl } 1020118611Snjl 1021118611Snjl /* Terminate walk at start op */ 1022118611Snjl 1023118611Snjl if (Op == StartOp) 1024118611Snjl { 1025118611Snjl break; 1026118611Snjl } 1027118611Snjl 1028118611Snjl /* No more children, visit peers */ 1029118611Snjl 1030118611Snjl if (Op->Asl.Next) 1031118611Snjl { 1032118611Snjl Op = Op->Asl.Next; 1033118611Snjl NodePreviouslyVisited = FALSE; 1034118611Snjl } 1035118611Snjl else 1036118611Snjl { 1037118611Snjl /* No children or peers, re-visit parent */ 1038118611Snjl 1039118611Snjl if (Level != 0 ) 1040118611Snjl { 1041118611Snjl Level--; 1042118611Snjl } 1043118611Snjl Op = Op->Asl.Parent; 1044118611Snjl NodePreviouslyVisited = TRUE; 1045118611Snjl } 1046118611Snjl } 1047118611Snjl break; 1048118611Snjl 1049118611Snjl 1050118611Snjl case ASL_WALK_VISIT_UPWARD: 1051118611Snjl 1052118611Snjl while (Op) 1053118611Snjl { 1054118611Snjl /* Visit leaf node (no children) or parent node on return trip */ 1055118611Snjl 1056118611Snjl if ((!Op->Asl.Child) || 1057118611Snjl (NodePreviouslyVisited)) 1058118611Snjl { 1059118611Snjl /* 1060118611Snjl * Let the callback process the node. 1061118611Snjl * 1062118611Snjl */ 1063118611Snjl Status = AscendingCallback (Op, Level, Context); 1064118611Snjl if (ACPI_FAILURE (Status)) 1065118611Snjl { 1066118611Snjl return (Status); 1067118611Snjl } 1068118611Snjl } 1069118611Snjl else 1070118611Snjl { 1071118611Snjl /* Visit children first, once */ 1072118611Snjl 1073118611Snjl Level++; 1074118611Snjl Op = Op->Asl.Child; 1075118611Snjl continue; 1076118611Snjl } 1077118611Snjl 1078118611Snjl /* Terminate walk at start op */ 1079118611Snjl 1080118611Snjl if (Op == StartOp) 1081118611Snjl { 1082118611Snjl break; 1083118611Snjl } 1084118611Snjl 1085118611Snjl /* No more children, visit peers */ 1086118611Snjl 1087118611Snjl if (Op->Asl.Next) 1088118611Snjl { 1089118611Snjl Op = Op->Asl.Next; 1090118611Snjl NodePreviouslyVisited = FALSE; 1091118611Snjl } 1092118611Snjl else 1093118611Snjl { 1094118611Snjl /* No children or peers, re-visit parent */ 1095118611Snjl 1096118611Snjl if (Level != 0 ) 1097118611Snjl { 1098118611Snjl Level--; 1099118611Snjl } 1100118611Snjl Op = Op->Asl.Parent; 1101118611Snjl NodePreviouslyVisited = TRUE; 1102118611Snjl } 1103118611Snjl } 1104118611Snjl break; 1105118611Snjl 1106118611Snjl 1107118611Snjl case ASL_WALK_VISIT_TWICE: 1108118611Snjl 1109118611Snjl while (Op) 1110118611Snjl { 1111118611Snjl if (NodePreviouslyVisited) 1112118611Snjl { 1113118611Snjl Status = AscendingCallback (Op, Level, Context); 1114118611Snjl if (ACPI_FAILURE (Status)) 1115118611Snjl { 1116118611Snjl return (Status); 1117118611Snjl } 1118118611Snjl } 1119118611Snjl else 1120118611Snjl { 1121118611Snjl /* 1122118611Snjl * Let the callback process the node. 1123118611Snjl */ 1124118611Snjl Status = DescendingCallback (Op, Level, Context); 1125118611Snjl if (ACPI_SUCCESS (Status)) 1126118611Snjl { 1127118611Snjl /* Visit children first, once */ 1128118611Snjl 1129118611Snjl if (Op->Asl.Child) 1130118611Snjl { 1131118611Snjl Level++; 1132118611Snjl Op = Op->Asl.Child; 1133118611Snjl continue; 1134118611Snjl } 1135118611Snjl } 1136118611Snjl else if (Status != AE_CTRL_DEPTH) 1137118611Snjl { 1138118611Snjl /* Exit immediately on any error */ 1139118611Snjl 1140118611Snjl return (Status); 1141118611Snjl } 1142118611Snjl } 1143118611Snjl 1144118611Snjl /* Terminate walk at start op */ 1145118611Snjl 1146118611Snjl if (Op == StartOp) 1147118611Snjl { 1148118611Snjl break; 1149118611Snjl } 1150118611Snjl 1151118611Snjl /* No more children, visit peers */ 1152118611Snjl 1153118611Snjl if (Op->Asl.Next) 1154118611Snjl { 1155118611Snjl Op = Op->Asl.Next; 1156118611Snjl NodePreviouslyVisited = FALSE; 1157118611Snjl } 1158118611Snjl else 1159118611Snjl { 1160118611Snjl /* No children or peers, re-visit parent */ 1161118611Snjl 1162118611Snjl if (Level != 0 ) 1163118611Snjl { 1164118611Snjl Level--; 1165118611Snjl } 1166118611Snjl Op = Op->Asl.Parent; 1167118611Snjl NodePreviouslyVisited = TRUE; 1168118611Snjl } 1169118611Snjl } 1170118611Snjl break; 1171118611Snjl 1172118611Snjl default: 1173118611Snjl /* No other types supported */ 1174118611Snjl break; 1175118611Snjl } 1176118611Snjl 1177118611Snjl /* If we get here, the walk completed with no errors */ 1178118611Snjl 1179118611Snjl return (AE_OK); 1180118611Snjl} 1181118611Snjl 1182118611Snjl 1183