1118611Snjl 2118611Snjl/****************************************************************************** 3118611Snjl * 4118611Snjl * Module Name: asltree - parse tree management 5118611Snjl * 6118611Snjl *****************************************************************************/ 7118611Snjl 8217365Sjkim/* 9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 10118611Snjl * All rights reserved. 11118611Snjl * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 26118611Snjl * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 30118611Snjl * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 44118611Snjl 45118611Snjl 46151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 47118611Snjl#include "aslcompiler.y.h" 48218590Sjkim#include <time.h> 49118611Snjl 50118611Snjl#define _COMPONENT ACPI_COMPILER 51118611Snjl ACPI_MODULE_NAME ("asltree") 52118611Snjl 53151937Sjkim/* Local prototypes */ 54118611Snjl 55151937Sjkimstatic ACPI_PARSE_OBJECT * 56151937SjkimTrGetNextNode ( 57151937Sjkim void); 58151937Sjkim 59151937Sjkimstatic char * 60151937SjkimTrGetNodeFlagName ( 61151937Sjkim UINT32 Flags); 62151937Sjkim 63151937Sjkim 64118611Snjl/******************************************************************************* 65118611Snjl * 66118611Snjl * FUNCTION: TrGetNextNode 67118611Snjl * 68118611Snjl * PARAMETERS: None 69118611Snjl * 70118611Snjl * RETURN: New parse node. Aborts on allocation failure 71118611Snjl * 72118611Snjl * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 73118611Snjl * dynamic memory manager for performance reasons (This has a 74118611Snjl * major impact on the speed of the compiler.) 75118611Snjl * 76118611Snjl ******************************************************************************/ 77118611Snjl 78151937Sjkimstatic ACPI_PARSE_OBJECT * 79151937SjkimTrGetNextNode ( 80151937Sjkim void) 81118611Snjl{ 82118611Snjl 83118611Snjl if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast) 84118611Snjl { 85151937Sjkim Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) * 86151937Sjkim ASL_NODE_CACHE_SIZE); 87118611Snjl Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE; 88118611Snjl } 89118611Snjl 90118611Snjl return (Gbl_NodeCacheNext++); 91118611Snjl} 92118611Snjl 93118611Snjl 94118611Snjl/******************************************************************************* 95118611Snjl * 96118611Snjl * FUNCTION: TrAllocateNode 97118611Snjl * 98118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 99118611Snjl * 100118611Snjl * RETURN: New parse node. Aborts on allocation failure 101118611Snjl * 102118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 103118611Snjl * 104118611Snjl ******************************************************************************/ 105118611Snjl 106118611SnjlACPI_PARSE_OBJECT * 107118611SnjlTrAllocateNode ( 108118611Snjl UINT32 ParseOpcode) 109118611Snjl{ 110118611Snjl ACPI_PARSE_OBJECT *Op; 111118611Snjl 112118611Snjl 113118611Snjl Op = TrGetNextNode (); 114118611Snjl 115118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 116118611Snjl Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 117118611Snjl Op->Asl.LineNumber = Gbl_CurrentLineNumber; 118118611Snjl Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 119118611Snjl Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 120118611Snjl Op->Asl.Column = Gbl_CurrentColumn; 121118611Snjl 122118611Snjl UtSetParseOpName (Op); 123118611Snjl return Op; 124118611Snjl} 125118611Snjl 126118611Snjl 127118611Snjl/******************************************************************************* 128118611Snjl * 129118611Snjl * FUNCTION: TrReleaseNode 130118611Snjl * 131118611Snjl * PARAMETERS: Op - Op to be released 132118611Snjl * 133118611Snjl * RETURN: None 134118611Snjl * 135118611Snjl * DESCRIPTION: "release" a node. In truth, nothing is done since the node 136118611Snjl * is part of a larger buffer 137118611Snjl * 138118611Snjl ******************************************************************************/ 139118611Snjl 140118611Snjlvoid 141118611SnjlTrReleaseNode ( 142118611Snjl ACPI_PARSE_OBJECT *Op) 143118611Snjl{ 144118611Snjl 145118611Snjl return; 146118611Snjl} 147118611Snjl 148118611Snjl 149118611Snjl/******************************************************************************* 150118611Snjl * 151118611Snjl * FUNCTION: TrUpdateNode 152118611Snjl * 153118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 154118611Snjl * Op - An existing parse node 155118611Snjl * 156118611Snjl * RETURN: The updated node 157118611Snjl * 158118611Snjl * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 159118611Snjl * change an opcode to DEFAULT_ARG so that the node is ignored 160118611Snjl * during the code generation. Also used to set generic integers 161118611Snjl * to a specific size (8, 16, 32, or 64 bits) 162118611Snjl * 163118611Snjl ******************************************************************************/ 164118611Snjl 165118611SnjlACPI_PARSE_OBJECT * 166118611SnjlTrUpdateNode ( 167118611Snjl UINT32 ParseOpcode, 168118611Snjl ACPI_PARSE_OBJECT *Op) 169118611Snjl{ 170118611Snjl 171118611Snjl if (!Op) 172118611Snjl { 173118611Snjl return NULL; 174118611Snjl } 175118611Snjl 176118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 177118611Snjl "\nUpdateNode: Old - %s, New - %s\n\n", 178118611Snjl UtGetOpName (Op->Asl.ParseOpcode), 179118611Snjl UtGetOpName (ParseOpcode)); 180118611Snjl 181118611Snjl /* Assign new opcode and name */ 182118611Snjl 183118611Snjl if (Op->Asl.ParseOpcode == PARSEOP_ONES) 184118611Snjl { 185118611Snjl switch (ParseOpcode) 186118611Snjl { 187118611Snjl case PARSEOP_BYTECONST: 188118611Snjl Op->Asl.Value.Integer = 0xFF; 189118611Snjl break; 190118611Snjl 191118611Snjl case PARSEOP_WORDCONST: 192118611Snjl Op->Asl.Value.Integer = 0xFFFF; 193118611Snjl break; 194118611Snjl 195118611Snjl case PARSEOP_DWORDCONST: 196118611Snjl Op->Asl.Value.Integer = 0xFFFFFFFF; 197118611Snjl break; 198118611Snjl 199118611Snjl default: 200118611Snjl /* Don't care about others, don't need to check QWORD */ 201118611Snjl break; 202118611Snjl } 203118611Snjl } 204118611Snjl 205118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 206118611Snjl UtSetParseOpName (Op); 207118611Snjl 208118611Snjl /* 209118611Snjl * For the BYTE, WORD, and DWORD constants, make sure that the integer 210118611Snjl * that was passed in will actually fit into the data type 211118611Snjl */ 212118611Snjl switch (ParseOpcode) 213118611Snjl { 214118611Snjl case PARSEOP_BYTECONST: 215118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 216118611Snjl break; 217118611Snjl 218118611Snjl case PARSEOP_WORDCONST: 219118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 220118611Snjl break; 221118611Snjl 222118611Snjl case PARSEOP_DWORDCONST: 223118611Snjl Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 224118611Snjl break; 225118611Snjl 226118611Snjl default: 227118611Snjl /* Don't care about others, don't need to check QWORD */ 228118611Snjl break; 229118611Snjl } 230118611Snjl 231118611Snjl return Op; 232118611Snjl} 233118611Snjl 234118611Snjl 235118611Snjl/******************************************************************************* 236118611Snjl * 237118611Snjl * FUNCTION: TrGetNodeFlagName 238118611Snjl * 239118611Snjl * PARAMETERS: Flags - Flags word to be decoded 240118611Snjl * 241151937Sjkim * RETURN: Name string. Always returns a valid string pointer. 242118611Snjl * 243118611Snjl * DESCRIPTION: Decode a flags word 244118611Snjl * 245118611Snjl ******************************************************************************/ 246118611Snjl 247151937Sjkimstatic char * 248118611SnjlTrGetNodeFlagName ( 249118611Snjl UINT32 Flags) 250118611Snjl{ 251118611Snjl 252118611Snjl switch (Flags) 253118611Snjl { 254118611Snjl case NODE_VISITED: 255118611Snjl return ("NODE_VISITED"); 256118611Snjl 257118611Snjl case NODE_AML_PACKAGE: 258118611Snjl return ("NODE_AML_PACKAGE"); 259118611Snjl 260118611Snjl case NODE_IS_TARGET: 261118611Snjl return ("NODE_IS_TARGET"); 262118611Snjl 263118611Snjl case NODE_IS_RESOURCE_DESC: 264118611Snjl return ("NODE_IS_RESOURCE_DESC"); 265118611Snjl 266118611Snjl case NODE_IS_RESOURCE_FIELD: 267118611Snjl return ("NODE_IS_RESOURCE_FIELD"); 268118611Snjl 269118611Snjl case NODE_HAS_NO_EXIT: 270118611Snjl return ("NODE_HAS_NO_EXIT"); 271118611Snjl 272118611Snjl case NODE_IF_HAS_NO_EXIT: 273118611Snjl return ("NODE_IF_HAS_NO_EXIT"); 274118611Snjl 275118611Snjl case NODE_NAME_INTERNALIZED: 276118611Snjl return ("NODE_NAME_INTERNALIZED"); 277118611Snjl 278118611Snjl case NODE_METHOD_NO_RETVAL: 279118611Snjl return ("NODE_METHOD_NO_RETVAL"); 280118611Snjl 281118611Snjl case NODE_METHOD_SOME_NO_RETVAL: 282118611Snjl return ("NODE_METHOD_SOME_NO_RETVAL"); 283118611Snjl 284118611Snjl case NODE_RESULT_NOT_USED: 285118611Snjl return ("NODE_RESULT_NOT_USED"); 286118611Snjl 287118611Snjl case NODE_METHOD_TYPED: 288118611Snjl return ("NODE_METHOD_TYPED"); 289118611Snjl 290118611Snjl case NODE_IS_BIT_OFFSET: 291118611Snjl return ("NODE_IS_BIT_OFFSET"); 292118611Snjl 293118611Snjl case NODE_COMPILE_TIME_CONST: 294118611Snjl return ("NODE_COMPILE_TIME_CONST"); 295118611Snjl 296118611Snjl case NODE_IS_TERM_ARG: 297118611Snjl return ("NODE_IS_TERM_ARG"); 298118611Snjl 299118611Snjl case NODE_WAS_ONES_OP: 300118611Snjl return ("NODE_WAS_ONES_OP"); 301118611Snjl 302118611Snjl case NODE_IS_NAME_DECLARATION: 303118611Snjl return ("NODE_IS_NAME_DECLARATION"); 304118611Snjl 305118611Snjl default: 306118611Snjl return ("Multiple Flags (or unknown flag) set"); 307118611Snjl } 308118611Snjl} 309118611Snjl 310118611Snjl 311118611Snjl/******************************************************************************* 312118611Snjl * 313118611Snjl * FUNCTION: TrSetNodeFlags 314118611Snjl * 315151937Sjkim * PARAMETERS: Op - An existing parse node 316118611Snjl * Flags - New flags word 317118611Snjl * 318151937Sjkim * RETURN: The updated parser op 319118611Snjl * 320118611Snjl * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 321118611Snjl * 322118611Snjl ******************************************************************************/ 323118611Snjl 324118611SnjlACPI_PARSE_OBJECT * 325118611SnjlTrSetNodeFlags ( 326118611Snjl ACPI_PARSE_OBJECT *Op, 327118611Snjl UINT32 Flags) 328118611Snjl{ 329118611Snjl 330118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 331151937Sjkim "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags, 332151937Sjkim TrGetNodeFlagName (Flags)); 333118611Snjl 334118611Snjl if (!Op) 335118611Snjl { 336118611Snjl return NULL; 337118611Snjl } 338118611Snjl 339118611Snjl Op->Asl.CompileFlags |= Flags; 340118611Snjl 341118611Snjl return Op; 342118611Snjl} 343118611Snjl 344118611Snjl 345118611Snjl/******************************************************************************* 346118611Snjl * 347118611Snjl * FUNCTION: TrSetEndLineNumber 348118611Snjl * 349118611Snjl * PARAMETERS: Op - An existing parse node 350118611Snjl * 351118611Snjl * RETURN: None. 352118611Snjl * 353118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 354118611Snjl * parse node to the current line numbers. 355118611Snjl * 356118611Snjl ******************************************************************************/ 357118611Snjl 358118611Snjlvoid 359118611SnjlTrSetEndLineNumber ( 360118611Snjl ACPI_PARSE_OBJECT *Op) 361118611Snjl{ 362118611Snjl 363118611Snjl /* If the end line # is already set, just return */ 364118611Snjl 365118611Snjl if (Op->Asl.EndLine) 366118611Snjl { 367118611Snjl return; 368118611Snjl } 369118611Snjl 370118611Snjl Op->Asl.EndLine = Gbl_CurrentLineNumber; 371118611Snjl Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 372118611Snjl} 373118611Snjl 374118611Snjl 375118611Snjl/******************************************************************************* 376118611Snjl * 377118611Snjl * FUNCTION: TrCreateLeafNode 378118611Snjl * 379118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 380118611Snjl * 381118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 382118611Snjl * 383118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 384118611Snjl * assigned to the node) 385118611Snjl * 386118611Snjl ******************************************************************************/ 387118611Snjl 388118611SnjlACPI_PARSE_OBJECT * 389118611SnjlTrCreateLeafNode ( 390118611Snjl UINT32 ParseOpcode) 391118611Snjl{ 392118611Snjl ACPI_PARSE_OBJECT *Op; 393118611Snjl 394118611Snjl 395118611Snjl Op = TrAllocateNode (ParseOpcode); 396118611Snjl 397118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 398209746Sjkim "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 399167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode)); 400118611Snjl 401118611Snjl return Op; 402118611Snjl} 403118611Snjl 404118611Snjl 405118611Snjl/******************************************************************************* 406118611Snjl * 407218590Sjkim * FUNCTION: TrCreateConstantLeafNode 408218590Sjkim * 409218590Sjkim * PARAMETERS: ParseOpcode - The constant opcode 410218590Sjkim * 411218590Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 412218590Sjkim * 413218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the 414218590Sjkim * special constants - __LINE__, __FILE__, and __DATE__. 415218590Sjkim * 416218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't 417218590Sjkim * have a full parse tree at this time and cannot find the parent control 418218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after 419218590Sjkim * the parse tree has been fully constructed. 420218590Sjkim * 421218590Sjkim ******************************************************************************/ 422218590Sjkim 423218590SjkimACPI_PARSE_OBJECT * 424218590SjkimTrCreateConstantLeafNode ( 425218590Sjkim UINT32 ParseOpcode) 426218590Sjkim{ 427218590Sjkim ACPI_PARSE_OBJECT *Op = NULL; 428218590Sjkim time_t CurrentTime; 429218590Sjkim char *StaticTimeString; 430218590Sjkim char *TimeString; 431218590Sjkim 432218590Sjkim 433218590Sjkim switch (ParseOpcode) 434218590Sjkim { 435218590Sjkim case PARSEOP___LINE__: 436218590Sjkim Op = TrAllocateNode (PARSEOP_INTEGER); 437218590Sjkim Op->Asl.Value.Integer = Op->Asl.LineNumber; 438218590Sjkim break; 439218590Sjkim 440218590Sjkim case PARSEOP___FILE__: 441218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 442218590Sjkim 443218590Sjkim /* Op.Asl.Filename contains the full pathname to the file */ 444218590Sjkim 445218590Sjkim Op->Asl.Value.String = Op->Asl.Filename; 446218590Sjkim break; 447218590Sjkim 448218590Sjkim case PARSEOP___DATE__: 449218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 450218590Sjkim 451218590Sjkim /* Get a copy of the current time */ 452218590Sjkim 453218590Sjkim CurrentTime = time (NULL); 454218590Sjkim StaticTimeString = ctime (&CurrentTime); 455218590Sjkim TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 456218590Sjkim strcpy (TimeString, StaticTimeString); 457218590Sjkim 458218590Sjkim TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 459218590Sjkim Op->Asl.Value.String = TimeString; 460218590Sjkim break; 461218590Sjkim 462218590Sjkim default: /* This would be an internal error */ 463218590Sjkim return (NULL); 464218590Sjkim } 465218590Sjkim 466218590Sjkim DbgPrint (ASL_PARSE_OUTPUT, 467218590Sjkim "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 468218590Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 469218590Sjkim ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 470218590Sjkim return (Op); 471218590Sjkim} 472218590Sjkim 473218590Sjkim 474218590Sjkim/******************************************************************************* 475218590Sjkim * 476118611Snjl * FUNCTION: TrCreateValuedLeafNode 477118611Snjl * 478118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 479118611Snjl * Value - Value to be assigned to the node 480118611Snjl * 481118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 482118611Snjl * 483118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value 484118611Snjl * assigned to it 485118611Snjl * 486118611Snjl ******************************************************************************/ 487118611Snjl 488118611SnjlACPI_PARSE_OBJECT * 489118611SnjlTrCreateValuedLeafNode ( 490118611Snjl UINT32 ParseOpcode, 491202771Sjkim UINT64 Value) 492118611Snjl{ 493118611Snjl ACPI_PARSE_OBJECT *Op; 494118611Snjl 495118611Snjl 496118611Snjl Op = TrAllocateNode (ParseOpcode); 497118611Snjl 498118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 499209746Sjkim "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 500167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 501123315Snjl ACPI_FORMAT_UINT64 (Value)); 502118611Snjl Op->Asl.Value.Integer = Value; 503118611Snjl 504118611Snjl switch (ParseOpcode) 505118611Snjl { 506118611Snjl case PARSEOP_STRING_LITERAL: 507118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 508118611Snjl break; 509118611Snjl 510118611Snjl case PARSEOP_NAMESEG: 511118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 512118611Snjl break; 513118611Snjl 514118611Snjl case PARSEOP_NAMESTRING: 515118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 516118611Snjl break; 517118611Snjl 518118611Snjl case PARSEOP_EISAID: 519118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 520118611Snjl break; 521118611Snjl 522118611Snjl case PARSEOP_METHOD: 523118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 524118611Snjl break; 525118611Snjl 526118611Snjl case PARSEOP_INTEGER: 527118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "INTEGER"); 528118611Snjl break; 529118611Snjl 530118611Snjl default: 531118611Snjl break; 532118611Snjl } 533118611Snjl 534118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 535118611Snjl return Op; 536118611Snjl} 537118611Snjl 538118611Snjl 539118611Snjl/******************************************************************************* 540118611Snjl * 541118611Snjl * FUNCTION: TrCreateNode 542118611Snjl * 543118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 544118611Snjl * NumChildren - Number of children to follow 545118611Snjl * ... - A list of child nodes to link to the new 546118611Snjl * node. NumChildren long. 547118611Snjl * 548118611Snjl * RETURN: Pointer to the new node. Aborts on allocation failure 549118611Snjl * 550118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child 551118611Snjl * nodes underneath the new node. 552118611Snjl * 553118611Snjl ******************************************************************************/ 554118611Snjl 555118611SnjlACPI_PARSE_OBJECT * 556118611SnjlTrCreateNode ( 557118611Snjl UINT32 ParseOpcode, 558118611Snjl UINT32 NumChildren, 559118611Snjl ...) 560118611Snjl{ 561118611Snjl ACPI_PARSE_OBJECT *Op; 562118611Snjl ACPI_PARSE_OBJECT *Child; 563118611Snjl ACPI_PARSE_OBJECT *PrevChild; 564118611Snjl va_list ap; 565118611Snjl UINT32 i; 566118611Snjl BOOLEAN FirstChild; 567118611Snjl 568118611Snjl 569118611Snjl va_start (ap, NumChildren); 570118611Snjl 571118611Snjl /* Allocate one new node */ 572118611Snjl 573118611Snjl Op = TrAllocateNode (ParseOpcode); 574118611Snjl 575118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 576209746Sjkim "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 577167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode)); 578118611Snjl 579118611Snjl /* Some extra debug output based on the parse opcode */ 580118611Snjl 581118611Snjl switch (ParseOpcode) 582118611Snjl { 583118611Snjl case PARSEOP_DEFINITIONBLOCK: 584118611Snjl RootNode = Op; 585118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 586118611Snjl break; 587118611Snjl 588118611Snjl case PARSEOP_OPERATIONREGION: 589118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 590118611Snjl break; 591118611Snjl 592118611Snjl case PARSEOP_OR: 593118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 594118611Snjl break; 595118611Snjl 596118611Snjl default: 597118611Snjl /* Nothing to do for other opcodes */ 598118611Snjl break; 599118611Snjl } 600118611Snjl 601118611Snjl /* Link the new node to its children */ 602118611Snjl 603118611Snjl PrevChild = NULL; 604118611Snjl FirstChild = TRUE; 605118611Snjl for (i = 0; i < NumChildren; i++) 606118611Snjl { 607118611Snjl /* Get the next child */ 608118611Snjl 609118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 610118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 611118611Snjl 612118611Snjl /* 613118611Snjl * If child is NULL, this means that an optional argument 614118611Snjl * was omitted. We must create a placeholder with a special 615118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 616118611Snjl * that it must emit the correct default for this argument 617118611Snjl */ 618118611Snjl if (!Child) 619118611Snjl { 620118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 621118611Snjl } 622118611Snjl 623118611Snjl /* Link first child to parent */ 624118611Snjl 625118611Snjl if (FirstChild) 626118611Snjl { 627118611Snjl FirstChild = FALSE; 628118611Snjl Op->Asl.Child = Child; 629118611Snjl } 630118611Snjl 631118611Snjl /* Point all children to parent */ 632118611Snjl 633118611Snjl Child->Asl.Parent = Op; 634118611Snjl 635118611Snjl /* Link children in a peer list */ 636118611Snjl 637118611Snjl if (PrevChild) 638118611Snjl { 639118611Snjl PrevChild->Asl.Next = Child; 640118611Snjl }; 641118611Snjl 642118611Snjl /* 643118611Snjl * This child might be a list, point all nodes in the list 644118611Snjl * to the same parent 645118611Snjl */ 646118611Snjl while (Child->Asl.Next) 647118611Snjl { 648118611Snjl Child = Child->Asl.Next; 649118611Snjl Child->Asl.Parent = Op; 650118611Snjl } 651118611Snjl 652118611Snjl PrevChild = Child; 653118611Snjl } 654118611Snjl va_end(ap); 655118611Snjl 656118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 657118611Snjl return Op; 658118611Snjl} 659118611Snjl 660118611Snjl 661118611Snjl/******************************************************************************* 662118611Snjl * 663118611Snjl * FUNCTION: TrLinkChildren 664118611Snjl * 665118611Snjl * PARAMETERS: Op - An existing parse node 666118611Snjl * NumChildren - Number of children to follow 667118611Snjl * ... - A list of child nodes to link to the new 668118611Snjl * node. NumChildren long. 669118611Snjl * 670118611Snjl * RETURN: The updated (linked) node 671118611Snjl * 672118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node 673118611Snjl * 674118611Snjl ******************************************************************************/ 675118611Snjl 676118611SnjlACPI_PARSE_OBJECT * 677118611SnjlTrLinkChildren ( 678118611Snjl ACPI_PARSE_OBJECT *Op, 679118611Snjl UINT32 NumChildren, 680118611Snjl ...) 681118611Snjl{ 682118611Snjl ACPI_PARSE_OBJECT *Child; 683118611Snjl ACPI_PARSE_OBJECT *PrevChild; 684118611Snjl va_list ap; 685118611Snjl UINT32 i; 686118611Snjl BOOLEAN FirstChild; 687118611Snjl 688118611Snjl 689118611Snjl va_start (ap, NumChildren); 690118611Snjl 691118611Snjl 692118611Snjl TrSetEndLineNumber (Op); 693118611Snjl 694118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 695209746Sjkim "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 696118611Snjl Op->Asl.LineNumber, Op->Asl.EndLine, 697118611Snjl Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 698118611Snjl 699118611Snjl switch (Op->Asl.ParseOpcode) 700118611Snjl { 701118611Snjl case PARSEOP_DEFINITIONBLOCK: 702118611Snjl RootNode = Op; 703118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 704118611Snjl break; 705118611Snjl 706118611Snjl case PARSEOP_OPERATIONREGION: 707118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 708118611Snjl break; 709118611Snjl 710118611Snjl case PARSEOP_OR: 711118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 712118611Snjl break; 713118611Snjl 714118611Snjl default: 715118611Snjl /* Nothing to do for other opcodes */ 716118611Snjl break; 717118611Snjl } 718118611Snjl 719118611Snjl /* Link the new node to it's children */ 720118611Snjl 721118611Snjl PrevChild = NULL; 722118611Snjl FirstChild = TRUE; 723118611Snjl for (i = 0; i < NumChildren; i++) 724118611Snjl { 725118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 726118611Snjl 727118611Snjl if ((Child == PrevChild) && (Child != NULL)) 728118611Snjl { 729151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 730151937Sjkim "Child node list invalid"); 731118611Snjl return Op; 732118611Snjl } 733118611Snjl 734118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 735118611Snjl 736118611Snjl /* 737118611Snjl * If child is NULL, this means that an optional argument 738118611Snjl * was omitted. We must create a placeholder with a special 739118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 740118611Snjl * that it must emit the correct default for this argument 741118611Snjl */ 742118611Snjl if (!Child) 743118611Snjl { 744118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 745118611Snjl } 746118611Snjl 747118611Snjl /* Link first child to parent */ 748118611Snjl 749118611Snjl if (FirstChild) 750118611Snjl { 751118611Snjl FirstChild = FALSE; 752118611Snjl Op->Asl.Child = Child; 753118611Snjl } 754118611Snjl 755118611Snjl /* Point all children to parent */ 756118611Snjl 757118611Snjl Child->Asl.Parent = Op; 758118611Snjl 759118611Snjl /* Link children in a peer list */ 760118611Snjl 761118611Snjl if (PrevChild) 762118611Snjl { 763118611Snjl PrevChild->Asl.Next = Child; 764118611Snjl }; 765118611Snjl 766118611Snjl /* 767118611Snjl * This child might be a list, point all nodes in the list 768118611Snjl * to the same parent 769118611Snjl */ 770118611Snjl while (Child->Asl.Next) 771118611Snjl { 772118611Snjl Child = Child->Asl.Next; 773118611Snjl Child->Asl.Parent = Op; 774118611Snjl } 775118611Snjl PrevChild = Child; 776118611Snjl } 777118611Snjl va_end(ap); 778118611Snjl 779118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 780118611Snjl return Op; 781118611Snjl} 782118611Snjl 783118611Snjl 784118611Snjl/******************************************************************************* 785118611Snjl * 786118611Snjl * FUNCTION: TrLinkPeerNode 787118611Snjl * 788118611Snjl * PARAMETERS: Op1 - First peer 789118611Snjl * Op2 - Second peer 790118611Snjl * 791118611Snjl * RETURN: Op1 or the non-null node. 792118611Snjl * 793118611Snjl * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 794118611Snjl * 795118611Snjl ******************************************************************************/ 796118611Snjl 797118611SnjlACPI_PARSE_OBJECT * 798118611SnjlTrLinkPeerNode ( 799118611Snjl ACPI_PARSE_OBJECT *Op1, 800118611Snjl ACPI_PARSE_OBJECT *Op2) 801118611Snjl{ 802118611Snjl ACPI_PARSE_OBJECT *Next; 803118611Snjl 804118611Snjl 805118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 806118611Snjl "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n", 807118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 808118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 809118611Snjl 810118611Snjl 811118611Snjl if ((!Op1) && (!Op2)) 812118611Snjl { 813118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 814118611Snjl return Op1; 815118611Snjl } 816118611Snjl 817118611Snjl /* If one of the nodes is null, just return the non-null node */ 818118611Snjl 819118611Snjl if (!Op2) 820118611Snjl { 821118611Snjl return Op1; 822118611Snjl } 823118611Snjl 824118611Snjl if (!Op1) 825118611Snjl { 826118611Snjl return Op2; 827118611Snjl } 828118611Snjl 829118611Snjl if (Op1 == Op2) 830118611Snjl { 831118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 832151937Sjkim "\n\n************* Internal error, linking node to itself %p\n\n\n", 833151937Sjkim Op1); 834151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 835151937Sjkim "Linking node to itself"); 836118611Snjl return Op1; 837118611Snjl } 838118611Snjl 839118611Snjl Op1->Asl.Parent = Op2->Asl.Parent; 840118611Snjl 841118611Snjl /* 842118611Snjl * Op 1 may already have a peer list (such as an IF/ELSE pair), 843118611Snjl * so we must walk to the end of the list and attach the new 844118611Snjl * peer at the end 845118611Snjl */ 846118611Snjl Next = Op1; 847118611Snjl while (Next->Asl.Next) 848118611Snjl { 849118611Snjl Next = Next->Asl.Next; 850118611Snjl } 851118611Snjl 852118611Snjl Next->Asl.Next = Op2; 853118611Snjl return Op1; 854118611Snjl} 855118611Snjl 856118611Snjl 857118611Snjl/******************************************************************************* 858118611Snjl * 859118611Snjl * FUNCTION: TrLinkPeerNodes 860118611Snjl * 861118611Snjl * PARAMETERS: NumPeers - The number of nodes in the list to follow 862118611Snjl * ... - A list of nodes to link together as peers 863118611Snjl * 864118611Snjl * RETURN: The first node in the list (head of the peer list) 865118611Snjl * 866118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes. 867118611Snjl * 868118611Snjl ******************************************************************************/ 869118611Snjl 870118611SnjlACPI_PARSE_OBJECT * 871118611SnjlTrLinkPeerNodes ( 872118611Snjl UINT32 NumPeers, 873118611Snjl ...) 874118611Snjl{ 875118611Snjl ACPI_PARSE_OBJECT *This; 876118611Snjl ACPI_PARSE_OBJECT *Next; 877118611Snjl va_list ap; 878118611Snjl UINT32 i; 879118611Snjl ACPI_PARSE_OBJECT *Start; 880118611Snjl 881118611Snjl 882118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 883209746Sjkim "\nLinkPeerNodes: (%u) ", NumPeers); 884118611Snjl 885118611Snjl va_start (ap, NumPeers); 886118611Snjl This = va_arg (ap, ACPI_PARSE_OBJECT *); 887118611Snjl Start = This; 888118611Snjl 889118611Snjl /* 890118611Snjl * Link all peers 891118611Snjl */ 892118611Snjl for (i = 0; i < (NumPeers -1); i++) 893118611Snjl { 894209746Sjkim DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 895118611Snjl 896118611Snjl while (This->Asl.Next) 897118611Snjl { 898118611Snjl This = This->Asl.Next; 899118611Snjl } 900118611Snjl 901118611Snjl /* Get another peer node */ 902118611Snjl 903118611Snjl Next = va_arg (ap, ACPI_PARSE_OBJECT *); 904118611Snjl if (!Next) 905118611Snjl { 906118611Snjl Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 907118611Snjl } 908118611Snjl 909118611Snjl /* link new node to the current node */ 910118611Snjl 911118611Snjl This->Asl.Next = Next; 912118611Snjl This = Next; 913118611Snjl } 914193529Sjkim va_end (ap); 915118611Snjl 916118611Snjl DbgPrint (ASL_PARSE_OUTPUT,"\n\n"); 917118611Snjl return (Start); 918118611Snjl} 919118611Snjl 920118611Snjl 921118611Snjl/******************************************************************************* 922118611Snjl * 923118611Snjl * FUNCTION: TrLinkChildNode 924118611Snjl * 925118611Snjl * PARAMETERS: Op1 - Parent node 926118611Snjl * Op2 - Op to become a child 927118611Snjl * 928118611Snjl * RETURN: The parent node 929118611Snjl * 930118611Snjl * DESCRIPTION: Link two nodes together as a parent and child 931118611Snjl * 932118611Snjl ******************************************************************************/ 933118611Snjl 934118611SnjlACPI_PARSE_OBJECT * 935118611SnjlTrLinkChildNode ( 936118611Snjl ACPI_PARSE_OBJECT *Op1, 937118611Snjl ACPI_PARSE_OBJECT *Op2) 938118611Snjl{ 939118611Snjl ACPI_PARSE_OBJECT *Next; 940118611Snjl 941118611Snjl 942118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 943118611Snjl "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n", 944118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 945118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 946118611Snjl 947118611Snjl if (!Op1 || !Op2) 948118611Snjl { 949118611Snjl return Op1; 950118611Snjl } 951118611Snjl 952118611Snjl Op1->Asl.Child = Op2; 953118611Snjl 954118611Snjl /* Set the child and all peers of the child to point to the parent */ 955118611Snjl 956118611Snjl Next = Op2; 957118611Snjl while (Next) 958118611Snjl { 959118611Snjl Next->Asl.Parent = Op1; 960118611Snjl Next = Next->Asl.Next; 961118611Snjl } 962118611Snjl 963118611Snjl return Op1; 964118611Snjl} 965118611Snjl 966118611Snjl 967118611Snjl/******************************************************************************* 968118611Snjl * 969118611Snjl * FUNCTION: TrWalkParseTree 970118611Snjl * 971118611Snjl * PARAMETERS: Visitation - Type of walk 972118611Snjl * DescendingCallback - Called during tree descent 973118611Snjl * AscendingCallback - Called during tree ascent 974118611Snjl * Context - To be passed to the callbacks 975118611Snjl * 976118611Snjl * RETURN: Status from callback(s) 977118611Snjl * 978118611Snjl * DESCRIPTION: Walk the entire parse tree. 979118611Snjl * 980118611Snjl ******************************************************************************/ 981118611Snjl 982118611SnjlACPI_STATUS 983118611SnjlTrWalkParseTree ( 984118611Snjl ACPI_PARSE_OBJECT *Op, 985118611Snjl UINT32 Visitation, 986118611Snjl ASL_WALK_CALLBACK DescendingCallback, 987118611Snjl ASL_WALK_CALLBACK AscendingCallback, 988118611Snjl void *Context) 989118611Snjl{ 990118611Snjl UINT32 Level; 991118611Snjl BOOLEAN NodePreviouslyVisited; 992118611Snjl ACPI_PARSE_OBJECT *StartOp = Op; 993118611Snjl ACPI_STATUS Status; 994118611Snjl 995118611Snjl 996118611Snjl if (!RootNode) 997118611Snjl { 998118611Snjl return (AE_OK); 999118611Snjl } 1000118611Snjl 1001118611Snjl Level = 0; 1002118611Snjl NodePreviouslyVisited = FALSE; 1003118611Snjl 1004118611Snjl switch (Visitation) 1005118611Snjl { 1006118611Snjl case ASL_WALK_VISIT_DOWNWARD: 1007118611Snjl 1008118611Snjl while (Op) 1009118611Snjl { 1010118611Snjl if (!NodePreviouslyVisited) 1011118611Snjl { 1012151937Sjkim /* Let the callback process the node. */ 1013151937Sjkim 1014118611Snjl Status = DescendingCallback (Op, Level, Context); 1015118611Snjl if (ACPI_SUCCESS (Status)) 1016118611Snjl { 1017118611Snjl /* Visit children first, once */ 1018118611Snjl 1019118611Snjl if (Op->Asl.Child) 1020118611Snjl { 1021118611Snjl Level++; 1022118611Snjl Op = Op->Asl.Child; 1023118611Snjl continue; 1024118611Snjl } 1025118611Snjl } 1026118611Snjl else if (Status != AE_CTRL_DEPTH) 1027118611Snjl { 1028118611Snjl /* Exit immediately on any error */ 1029118611Snjl 1030118611Snjl return (Status); 1031118611Snjl } 1032118611Snjl } 1033118611Snjl 1034118611Snjl /* Terminate walk at start op */ 1035118611Snjl 1036118611Snjl if (Op == StartOp) 1037118611Snjl { 1038118611Snjl break; 1039118611Snjl } 1040118611Snjl 1041118611Snjl /* No more children, visit peers */ 1042118611Snjl 1043118611Snjl if (Op->Asl.Next) 1044118611Snjl { 1045118611Snjl Op = Op->Asl.Next; 1046118611Snjl NodePreviouslyVisited = FALSE; 1047118611Snjl } 1048118611Snjl else 1049118611Snjl { 1050118611Snjl /* No children or peers, re-visit parent */ 1051118611Snjl 1052118611Snjl if (Level != 0 ) 1053118611Snjl { 1054118611Snjl Level--; 1055118611Snjl } 1056118611Snjl Op = Op->Asl.Parent; 1057118611Snjl NodePreviouslyVisited = TRUE; 1058118611Snjl } 1059118611Snjl } 1060118611Snjl break; 1061118611Snjl 1062118611Snjl 1063118611Snjl case ASL_WALK_VISIT_UPWARD: 1064118611Snjl 1065118611Snjl while (Op) 1066118611Snjl { 1067118611Snjl /* Visit leaf node (no children) or parent node on return trip */ 1068118611Snjl 1069118611Snjl if ((!Op->Asl.Child) || 1070118611Snjl (NodePreviouslyVisited)) 1071118611Snjl { 1072151937Sjkim /* Let the callback process the node. */ 1073151937Sjkim 1074118611Snjl Status = AscendingCallback (Op, Level, Context); 1075118611Snjl if (ACPI_FAILURE (Status)) 1076118611Snjl { 1077118611Snjl return (Status); 1078118611Snjl } 1079118611Snjl } 1080118611Snjl else 1081118611Snjl { 1082118611Snjl /* Visit children first, once */ 1083118611Snjl 1084118611Snjl Level++; 1085118611Snjl Op = Op->Asl.Child; 1086118611Snjl continue; 1087118611Snjl } 1088118611Snjl 1089118611Snjl /* Terminate walk at start op */ 1090118611Snjl 1091118611Snjl if (Op == StartOp) 1092118611Snjl { 1093118611Snjl break; 1094118611Snjl } 1095118611Snjl 1096118611Snjl /* No more children, visit peers */ 1097118611Snjl 1098118611Snjl if (Op->Asl.Next) 1099118611Snjl { 1100118611Snjl Op = Op->Asl.Next; 1101118611Snjl NodePreviouslyVisited = FALSE; 1102118611Snjl } 1103118611Snjl else 1104118611Snjl { 1105118611Snjl /* No children or peers, re-visit parent */ 1106118611Snjl 1107118611Snjl if (Level != 0 ) 1108118611Snjl { 1109118611Snjl Level--; 1110118611Snjl } 1111118611Snjl Op = Op->Asl.Parent; 1112118611Snjl NodePreviouslyVisited = TRUE; 1113118611Snjl } 1114118611Snjl } 1115118611Snjl break; 1116118611Snjl 1117118611Snjl 1118118611Snjl case ASL_WALK_VISIT_TWICE: 1119118611Snjl 1120118611Snjl while (Op) 1121118611Snjl { 1122118611Snjl if (NodePreviouslyVisited) 1123118611Snjl { 1124118611Snjl Status = AscendingCallback (Op, Level, Context); 1125118611Snjl if (ACPI_FAILURE (Status)) 1126118611Snjl { 1127118611Snjl return (Status); 1128118611Snjl } 1129118611Snjl } 1130118611Snjl else 1131118611Snjl { 1132151937Sjkim /* Let the callback process the node. */ 1133151937Sjkim 1134118611Snjl Status = DescendingCallback (Op, Level, Context); 1135118611Snjl if (ACPI_SUCCESS (Status)) 1136118611Snjl { 1137118611Snjl /* Visit children first, once */ 1138118611Snjl 1139118611Snjl if (Op->Asl.Child) 1140118611Snjl { 1141118611Snjl Level++; 1142118611Snjl Op = Op->Asl.Child; 1143118611Snjl continue; 1144118611Snjl } 1145118611Snjl } 1146118611Snjl else if (Status != AE_CTRL_DEPTH) 1147118611Snjl { 1148118611Snjl /* Exit immediately on any error */ 1149118611Snjl 1150118611Snjl return (Status); 1151118611Snjl } 1152118611Snjl } 1153118611Snjl 1154118611Snjl /* Terminate walk at start op */ 1155118611Snjl 1156118611Snjl if (Op == StartOp) 1157118611Snjl { 1158118611Snjl break; 1159118611Snjl } 1160118611Snjl 1161118611Snjl /* No more children, visit peers */ 1162118611Snjl 1163118611Snjl if (Op->Asl.Next) 1164118611Snjl { 1165118611Snjl Op = Op->Asl.Next; 1166118611Snjl NodePreviouslyVisited = FALSE; 1167118611Snjl } 1168118611Snjl else 1169118611Snjl { 1170118611Snjl /* No children or peers, re-visit parent */ 1171118611Snjl 1172118611Snjl if (Level != 0 ) 1173118611Snjl { 1174118611Snjl Level--; 1175118611Snjl } 1176118611Snjl Op = Op->Asl.Parent; 1177118611Snjl NodePreviouslyVisited = TRUE; 1178118611Snjl } 1179118611Snjl } 1180118611Snjl break; 1181118611Snjl 1182118611Snjl default: 1183118611Snjl /* No other types supported */ 1184118611Snjl break; 1185118611Snjl } 1186118611Snjl 1187118611Snjl /* If we get here, the walk completed with no errors */ 1188118611Snjl 1189118611Snjl return (AE_OK); 1190118611Snjl} 1191118611Snjl 1192118611Snjl 1193