asltree.c revision 241973
1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: asltree - parse tree management 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8229989Sjkim * Copyright (C) 2000 - 2012, Intel Corp. 9118611Snjl * All rights reserved. 10118611Snjl * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25118611Snjl * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29118611Snjl * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43118611Snjl 44118611Snjl 45151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 46118611Snjl#include "aslcompiler.y.h" 47228110Sjkim#include <contrib/dev/acpica/include/acapps.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 * 70239340Sjkim * RETURN: New parse node. Aborts on allocation failure 71118611Snjl * 72239340Sjkim * 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 * 100239340Sjkim * 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); 123241973Sjkim return (Op); 124118611Snjl} 125118611Snjl 126118611Snjl 127118611Snjl/******************************************************************************* 128118611Snjl * 129118611Snjl * FUNCTION: TrReleaseNode 130118611Snjl * 131118611Snjl * PARAMETERS: Op - Op to be released 132118611Snjl * 133118611Snjl * RETURN: None 134118611Snjl * 135239340Sjkim * 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 * 158239340Sjkim * 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 160239340Sjkim * 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 { 173241973Sjkim 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: 188239340Sjkim Op->Asl.Value.Integer = ACPI_UINT8_MAX; 189118611Snjl break; 190118611Snjl 191118611Snjl case PARSEOP_WORDCONST: 192239340Sjkim Op->Asl.Value.Integer = ACPI_UINT16_MAX; 193118611Snjl break; 194118611Snjl 195118611Snjl case PARSEOP_DWORDCONST: 196239340Sjkim Op->Asl.Value.Integer = ACPI_UINT32_MAX; 197118611Snjl break; 198118611Snjl 199239340Sjkim /* Don't need to do the QWORD case */ 200239340Sjkim 201118611Snjl default: 202239340Sjkim /* Don't care about others */ 203118611Snjl break; 204118611Snjl } 205118611Snjl } 206118611Snjl 207118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 208118611Snjl UtSetParseOpName (Op); 209118611Snjl 210118611Snjl /* 211118611Snjl * For the BYTE, WORD, and DWORD constants, make sure that the integer 212118611Snjl * that was passed in will actually fit into the data type 213118611Snjl */ 214118611Snjl switch (ParseOpcode) 215118611Snjl { 216118611Snjl case PARSEOP_BYTECONST: 217239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 218239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT8_MAX; 219118611Snjl break; 220118611Snjl 221118611Snjl case PARSEOP_WORDCONST: 222239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 223239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT16_MAX; 224118611Snjl break; 225118611Snjl 226118611Snjl case PARSEOP_DWORDCONST: 227239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 228239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT32_MAX; 229118611Snjl break; 230118611Snjl 231118611Snjl default: 232118611Snjl /* Don't care about others, don't need to check QWORD */ 233118611Snjl break; 234118611Snjl } 235118611Snjl 236241973Sjkim return (Op); 237118611Snjl} 238118611Snjl 239118611Snjl 240118611Snjl/******************************************************************************* 241118611Snjl * 242118611Snjl * FUNCTION: TrGetNodeFlagName 243118611Snjl * 244118611Snjl * PARAMETERS: Flags - Flags word to be decoded 245118611Snjl * 246151937Sjkim * RETURN: Name string. Always returns a valid string pointer. 247118611Snjl * 248118611Snjl * DESCRIPTION: Decode a flags word 249118611Snjl * 250118611Snjl ******************************************************************************/ 251118611Snjl 252151937Sjkimstatic char * 253118611SnjlTrGetNodeFlagName ( 254118611Snjl UINT32 Flags) 255118611Snjl{ 256118611Snjl 257118611Snjl switch (Flags) 258118611Snjl { 259118611Snjl case NODE_VISITED: 260118611Snjl return ("NODE_VISITED"); 261118611Snjl 262118611Snjl case NODE_AML_PACKAGE: 263118611Snjl return ("NODE_AML_PACKAGE"); 264118611Snjl 265118611Snjl case NODE_IS_TARGET: 266118611Snjl return ("NODE_IS_TARGET"); 267118611Snjl 268118611Snjl case NODE_IS_RESOURCE_DESC: 269118611Snjl return ("NODE_IS_RESOURCE_DESC"); 270118611Snjl 271118611Snjl case NODE_IS_RESOURCE_FIELD: 272118611Snjl return ("NODE_IS_RESOURCE_FIELD"); 273118611Snjl 274118611Snjl case NODE_HAS_NO_EXIT: 275118611Snjl return ("NODE_HAS_NO_EXIT"); 276118611Snjl 277118611Snjl case NODE_IF_HAS_NO_EXIT: 278118611Snjl return ("NODE_IF_HAS_NO_EXIT"); 279118611Snjl 280118611Snjl case NODE_NAME_INTERNALIZED: 281118611Snjl return ("NODE_NAME_INTERNALIZED"); 282118611Snjl 283118611Snjl case NODE_METHOD_NO_RETVAL: 284118611Snjl return ("NODE_METHOD_NO_RETVAL"); 285118611Snjl 286118611Snjl case NODE_METHOD_SOME_NO_RETVAL: 287118611Snjl return ("NODE_METHOD_SOME_NO_RETVAL"); 288118611Snjl 289118611Snjl case NODE_RESULT_NOT_USED: 290118611Snjl return ("NODE_RESULT_NOT_USED"); 291118611Snjl 292118611Snjl case NODE_METHOD_TYPED: 293118611Snjl return ("NODE_METHOD_TYPED"); 294118611Snjl 295118611Snjl case NODE_COMPILE_TIME_CONST: 296118611Snjl return ("NODE_COMPILE_TIME_CONST"); 297118611Snjl 298118611Snjl case NODE_IS_TERM_ARG: 299118611Snjl return ("NODE_IS_TERM_ARG"); 300118611Snjl 301118611Snjl case NODE_WAS_ONES_OP: 302118611Snjl return ("NODE_WAS_ONES_OP"); 303118611Snjl 304118611Snjl case NODE_IS_NAME_DECLARATION: 305118611Snjl return ("NODE_IS_NAME_DECLARATION"); 306118611Snjl 307118611Snjl default: 308118611Snjl return ("Multiple Flags (or unknown flag) set"); 309118611Snjl } 310118611Snjl} 311118611Snjl 312118611Snjl 313118611Snjl/******************************************************************************* 314118611Snjl * 315118611Snjl * FUNCTION: TrSetNodeFlags 316118611Snjl * 317151937Sjkim * PARAMETERS: Op - An existing parse node 318118611Snjl * Flags - New flags word 319118611Snjl * 320151937Sjkim * RETURN: The updated parser op 321118611Snjl * 322239340Sjkim * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 323118611Snjl * 324118611Snjl ******************************************************************************/ 325118611Snjl 326118611SnjlACPI_PARSE_OBJECT * 327118611SnjlTrSetNodeFlags ( 328118611Snjl ACPI_PARSE_OBJECT *Op, 329118611Snjl UINT32 Flags) 330118611Snjl{ 331118611Snjl 332118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 333151937Sjkim "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags, 334151937Sjkim TrGetNodeFlagName (Flags)); 335118611Snjl 336118611Snjl if (!Op) 337118611Snjl { 338241973Sjkim return (NULL); 339118611Snjl } 340118611Snjl 341118611Snjl Op->Asl.CompileFlags |= Flags; 342239340Sjkim return (Op); 343239340Sjkim} 344118611Snjl 345239340Sjkim 346239340Sjkim/******************************************************************************* 347239340Sjkim * 348239340Sjkim * FUNCTION: TrSetNodeAmlLength 349239340Sjkim * 350239340Sjkim * PARAMETERS: Op - An existing parse node 351239340Sjkim * Length - AML Length 352239340Sjkim * 353239340Sjkim * RETURN: The updated parser op 354239340Sjkim * 355239340Sjkim * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate 356239340Sjkim * the presence of a node that must be reduced to a fixed length 357239340Sjkim * constant. 358239340Sjkim * 359239340Sjkim ******************************************************************************/ 360239340Sjkim 361239340SjkimACPI_PARSE_OBJECT * 362239340SjkimTrSetNodeAmlLength ( 363239340Sjkim ACPI_PARSE_OBJECT *Op, 364239340Sjkim UINT32 Length) 365239340Sjkim{ 366239340Sjkim 367239340Sjkim DbgPrint (ASL_PARSE_OUTPUT, 368239340Sjkim "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length); 369239340Sjkim 370239340Sjkim if (!Op) 371239340Sjkim { 372241973Sjkim return (NULL); 373239340Sjkim } 374239340Sjkim 375239340Sjkim Op->Asl.AmlLength = Length; 376239340Sjkim return (Op); 377118611Snjl} 378118611Snjl 379118611Snjl 380118611Snjl/******************************************************************************* 381118611Snjl * 382118611Snjl * FUNCTION: TrSetEndLineNumber 383118611Snjl * 384118611Snjl * PARAMETERS: Op - An existing parse node 385118611Snjl * 386118611Snjl * RETURN: None. 387118611Snjl * 388118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 389118611Snjl * parse node to the current line numbers. 390118611Snjl * 391118611Snjl ******************************************************************************/ 392118611Snjl 393118611Snjlvoid 394118611SnjlTrSetEndLineNumber ( 395118611Snjl ACPI_PARSE_OBJECT *Op) 396118611Snjl{ 397118611Snjl 398118611Snjl /* If the end line # is already set, just return */ 399118611Snjl 400118611Snjl if (Op->Asl.EndLine) 401118611Snjl { 402118611Snjl return; 403118611Snjl } 404118611Snjl 405118611Snjl Op->Asl.EndLine = Gbl_CurrentLineNumber; 406118611Snjl Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 407118611Snjl} 408118611Snjl 409118611Snjl 410118611Snjl/******************************************************************************* 411118611Snjl * 412118611Snjl * FUNCTION: TrCreateLeafNode 413118611Snjl * 414118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 415118611Snjl * 416239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 417118611Snjl * 418118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 419118611Snjl * assigned to the node) 420118611Snjl * 421118611Snjl ******************************************************************************/ 422118611Snjl 423118611SnjlACPI_PARSE_OBJECT * 424118611SnjlTrCreateLeafNode ( 425118611Snjl UINT32 ParseOpcode) 426118611Snjl{ 427118611Snjl ACPI_PARSE_OBJECT *Op; 428118611Snjl 429118611Snjl 430118611Snjl Op = TrAllocateNode (ParseOpcode); 431118611Snjl 432118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 433209746Sjkim "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 434167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode)); 435118611Snjl 436241973Sjkim return (Op); 437118611Snjl} 438118611Snjl 439118611Snjl 440118611Snjl/******************************************************************************* 441118611Snjl * 442218590Sjkim * FUNCTION: TrCreateConstantLeafNode 443218590Sjkim * 444218590Sjkim * PARAMETERS: ParseOpcode - The constant opcode 445218590Sjkim * 446239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 447218590Sjkim * 448218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the 449218590Sjkim * special constants - __LINE__, __FILE__, and __DATE__. 450218590Sjkim * 451218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't 452218590Sjkim * have a full parse tree at this time and cannot find the parent control 453218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after 454218590Sjkim * the parse tree has been fully constructed. 455218590Sjkim * 456218590Sjkim ******************************************************************************/ 457218590Sjkim 458218590SjkimACPI_PARSE_OBJECT * 459218590SjkimTrCreateConstantLeafNode ( 460218590Sjkim UINT32 ParseOpcode) 461218590Sjkim{ 462218590Sjkim ACPI_PARSE_OBJECT *Op = NULL; 463218590Sjkim time_t CurrentTime; 464218590Sjkim char *StaticTimeString; 465218590Sjkim char *TimeString; 466228110Sjkim char *Path; 467228110Sjkim char *Filename; 468218590Sjkim 469218590Sjkim 470218590Sjkim switch (ParseOpcode) 471218590Sjkim { 472218590Sjkim case PARSEOP___LINE__: 473218590Sjkim Op = TrAllocateNode (PARSEOP_INTEGER); 474218590Sjkim Op->Asl.Value.Integer = Op->Asl.LineNumber; 475218590Sjkim break; 476218590Sjkim 477228110Sjkim case PARSEOP___PATH__: 478218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 479218590Sjkim 480218590Sjkim /* Op.Asl.Filename contains the full pathname to the file */ 481218590Sjkim 482218590Sjkim Op->Asl.Value.String = Op->Asl.Filename; 483218590Sjkim break; 484218590Sjkim 485228110Sjkim case PARSEOP___FILE__: 486218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 487218590Sjkim 488228110Sjkim /* Get the simple filename from the full path */ 489228110Sjkim 490228110Sjkim FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename); 491228110Sjkim ACPI_FREE (Path); 492228110Sjkim Op->Asl.Value.String = Filename; 493228110Sjkim break; 494228110Sjkim 495228110Sjkim case PARSEOP___DATE__: 496228110Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 497228110Sjkim 498218590Sjkim /* Get a copy of the current time */ 499218590Sjkim 500218590Sjkim CurrentTime = time (NULL); 501218590Sjkim StaticTimeString = ctime (&CurrentTime); 502218590Sjkim TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 503218590Sjkim strcpy (TimeString, StaticTimeString); 504218590Sjkim 505218590Sjkim TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 506218590Sjkim Op->Asl.Value.String = TimeString; 507218590Sjkim break; 508218590Sjkim 509218590Sjkim default: /* This would be an internal error */ 510218590Sjkim return (NULL); 511218590Sjkim } 512218590Sjkim 513218590Sjkim DbgPrint (ASL_PARSE_OUTPUT, 514218590Sjkim "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 515218590Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 516218590Sjkim ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 517218590Sjkim return (Op); 518218590Sjkim} 519218590Sjkim 520218590Sjkim 521218590Sjkim/******************************************************************************* 522218590Sjkim * 523118611Snjl * FUNCTION: TrCreateValuedLeafNode 524118611Snjl * 525118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 526118611Snjl * Value - Value to be assigned to the node 527118611Snjl * 528239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 529118611Snjl * 530118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value 531118611Snjl * assigned to it 532118611Snjl * 533118611Snjl ******************************************************************************/ 534118611Snjl 535118611SnjlACPI_PARSE_OBJECT * 536118611SnjlTrCreateValuedLeafNode ( 537118611Snjl UINT32 ParseOpcode, 538202771Sjkim UINT64 Value) 539118611Snjl{ 540118611Snjl ACPI_PARSE_OBJECT *Op; 541118611Snjl 542118611Snjl 543118611Snjl Op = TrAllocateNode (ParseOpcode); 544118611Snjl 545118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 546209746Sjkim "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 547167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 548123315Snjl ACPI_FORMAT_UINT64 (Value)); 549118611Snjl Op->Asl.Value.Integer = Value; 550118611Snjl 551118611Snjl switch (ParseOpcode) 552118611Snjl { 553118611Snjl case PARSEOP_STRING_LITERAL: 554118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 555118611Snjl break; 556118611Snjl 557118611Snjl case PARSEOP_NAMESEG: 558118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 559118611Snjl break; 560118611Snjl 561118611Snjl case PARSEOP_NAMESTRING: 562118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 563118611Snjl break; 564118611Snjl 565118611Snjl case PARSEOP_EISAID: 566118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 567118611Snjl break; 568118611Snjl 569118611Snjl case PARSEOP_METHOD: 570118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 571118611Snjl break; 572118611Snjl 573118611Snjl case PARSEOP_INTEGER: 574118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "INTEGER"); 575118611Snjl break; 576118611Snjl 577118611Snjl default: 578118611Snjl break; 579118611Snjl } 580118611Snjl 581118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 582241973Sjkim return (Op); 583118611Snjl} 584118611Snjl 585118611Snjl 586118611Snjl/******************************************************************************* 587118611Snjl * 588118611Snjl * FUNCTION: TrCreateNode 589118611Snjl * 590118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 591118611Snjl * NumChildren - Number of children to follow 592118611Snjl * ... - A list of child nodes to link to the new 593239340Sjkim * node. NumChildren long. 594118611Snjl * 595239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 596118611Snjl * 597118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child 598118611Snjl * nodes underneath the new node. 599118611Snjl * 600118611Snjl ******************************************************************************/ 601118611Snjl 602118611SnjlACPI_PARSE_OBJECT * 603118611SnjlTrCreateNode ( 604118611Snjl UINT32 ParseOpcode, 605118611Snjl UINT32 NumChildren, 606118611Snjl ...) 607118611Snjl{ 608118611Snjl ACPI_PARSE_OBJECT *Op; 609118611Snjl ACPI_PARSE_OBJECT *Child; 610118611Snjl ACPI_PARSE_OBJECT *PrevChild; 611118611Snjl va_list ap; 612118611Snjl UINT32 i; 613118611Snjl BOOLEAN FirstChild; 614118611Snjl 615118611Snjl 616118611Snjl va_start (ap, NumChildren); 617118611Snjl 618118611Snjl /* Allocate one new node */ 619118611Snjl 620118611Snjl Op = TrAllocateNode (ParseOpcode); 621118611Snjl 622118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 623209746Sjkim "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 624167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode)); 625118611Snjl 626118611Snjl /* Some extra debug output based on the parse opcode */ 627118611Snjl 628118611Snjl switch (ParseOpcode) 629118611Snjl { 630118611Snjl case PARSEOP_DEFINITIONBLOCK: 631118611Snjl RootNode = Op; 632118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 633118611Snjl break; 634118611Snjl 635118611Snjl case PARSEOP_OPERATIONREGION: 636118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 637118611Snjl break; 638118611Snjl 639118611Snjl case PARSEOP_OR: 640118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 641118611Snjl break; 642118611Snjl 643118611Snjl default: 644118611Snjl /* Nothing to do for other opcodes */ 645118611Snjl break; 646118611Snjl } 647118611Snjl 648118611Snjl /* Link the new node to its children */ 649118611Snjl 650118611Snjl PrevChild = NULL; 651118611Snjl FirstChild = TRUE; 652118611Snjl for (i = 0; i < NumChildren; i++) 653118611Snjl { 654118611Snjl /* Get the next child */ 655118611Snjl 656118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 657118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 658118611Snjl 659118611Snjl /* 660118611Snjl * If child is NULL, this means that an optional argument 661239340Sjkim * was omitted. We must create a placeholder with a special 662118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 663118611Snjl * that it must emit the correct default for this argument 664118611Snjl */ 665118611Snjl if (!Child) 666118611Snjl { 667118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 668118611Snjl } 669118611Snjl 670118611Snjl /* Link first child to parent */ 671118611Snjl 672118611Snjl if (FirstChild) 673118611Snjl { 674118611Snjl FirstChild = FALSE; 675118611Snjl Op->Asl.Child = Child; 676118611Snjl } 677118611Snjl 678118611Snjl /* Point all children to parent */ 679118611Snjl 680118611Snjl Child->Asl.Parent = Op; 681118611Snjl 682118611Snjl /* Link children in a peer list */ 683118611Snjl 684118611Snjl if (PrevChild) 685118611Snjl { 686118611Snjl PrevChild->Asl.Next = Child; 687118611Snjl }; 688118611Snjl 689118611Snjl /* 690118611Snjl * This child might be a list, point all nodes in the list 691118611Snjl * to the same parent 692118611Snjl */ 693118611Snjl while (Child->Asl.Next) 694118611Snjl { 695118611Snjl Child = Child->Asl.Next; 696118611Snjl Child->Asl.Parent = Op; 697118611Snjl } 698118611Snjl 699118611Snjl PrevChild = Child; 700118611Snjl } 701118611Snjl va_end(ap); 702118611Snjl 703118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 704241973Sjkim return (Op); 705118611Snjl} 706118611Snjl 707118611Snjl 708118611Snjl/******************************************************************************* 709118611Snjl * 710118611Snjl * FUNCTION: TrLinkChildren 711118611Snjl * 712118611Snjl * PARAMETERS: Op - An existing parse node 713118611Snjl * NumChildren - Number of children to follow 714118611Snjl * ... - A list of child nodes to link to the new 715239340Sjkim * node. NumChildren long. 716118611Snjl * 717118611Snjl * RETURN: The updated (linked) node 718118611Snjl * 719118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node 720118611Snjl * 721118611Snjl ******************************************************************************/ 722118611Snjl 723118611SnjlACPI_PARSE_OBJECT * 724118611SnjlTrLinkChildren ( 725118611Snjl ACPI_PARSE_OBJECT *Op, 726118611Snjl UINT32 NumChildren, 727118611Snjl ...) 728118611Snjl{ 729118611Snjl ACPI_PARSE_OBJECT *Child; 730118611Snjl ACPI_PARSE_OBJECT *PrevChild; 731118611Snjl va_list ap; 732118611Snjl UINT32 i; 733118611Snjl BOOLEAN FirstChild; 734118611Snjl 735118611Snjl 736118611Snjl va_start (ap, NumChildren); 737118611Snjl 738118611Snjl 739118611Snjl TrSetEndLineNumber (Op); 740118611Snjl 741118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 742209746Sjkim "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 743118611Snjl Op->Asl.LineNumber, Op->Asl.EndLine, 744118611Snjl Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 745118611Snjl 746118611Snjl switch (Op->Asl.ParseOpcode) 747118611Snjl { 748118611Snjl case PARSEOP_DEFINITIONBLOCK: 749118611Snjl RootNode = Op; 750118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 751118611Snjl break; 752118611Snjl 753118611Snjl case PARSEOP_OPERATIONREGION: 754118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 755118611Snjl break; 756118611Snjl 757118611Snjl case PARSEOP_OR: 758118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 759118611Snjl break; 760118611Snjl 761118611Snjl default: 762118611Snjl /* Nothing to do for other opcodes */ 763118611Snjl break; 764118611Snjl } 765118611Snjl 766118611Snjl /* Link the new node to it's children */ 767118611Snjl 768118611Snjl PrevChild = NULL; 769118611Snjl FirstChild = TRUE; 770118611Snjl for (i = 0; i < NumChildren; i++) 771118611Snjl { 772118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 773118611Snjl 774118611Snjl if ((Child == PrevChild) && (Child != NULL)) 775118611Snjl { 776151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 777151937Sjkim "Child node list invalid"); 778241973Sjkim return (Op); 779118611Snjl } 780118611Snjl 781118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 782118611Snjl 783118611Snjl /* 784118611Snjl * If child is NULL, this means that an optional argument 785239340Sjkim * was omitted. We must create a placeholder with a special 786118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 787118611Snjl * that it must emit the correct default for this argument 788118611Snjl */ 789118611Snjl if (!Child) 790118611Snjl { 791118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 792118611Snjl } 793118611Snjl 794118611Snjl /* Link first child to parent */ 795118611Snjl 796118611Snjl if (FirstChild) 797118611Snjl { 798118611Snjl FirstChild = FALSE; 799118611Snjl Op->Asl.Child = Child; 800118611Snjl } 801118611Snjl 802118611Snjl /* Point all children to parent */ 803118611Snjl 804118611Snjl Child->Asl.Parent = Op; 805118611Snjl 806118611Snjl /* Link children in a peer list */ 807118611Snjl 808118611Snjl if (PrevChild) 809118611Snjl { 810118611Snjl PrevChild->Asl.Next = Child; 811118611Snjl }; 812118611Snjl 813118611Snjl /* 814118611Snjl * This child might be a list, point all nodes in the list 815118611Snjl * to the same parent 816118611Snjl */ 817118611Snjl while (Child->Asl.Next) 818118611Snjl { 819118611Snjl Child = Child->Asl.Next; 820118611Snjl Child->Asl.Parent = Op; 821118611Snjl } 822118611Snjl PrevChild = Child; 823118611Snjl } 824118611Snjl va_end(ap); 825118611Snjl 826118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 827241973Sjkim return (Op); 828118611Snjl} 829118611Snjl 830118611Snjl 831118611Snjl/******************************************************************************* 832118611Snjl * 833118611Snjl * FUNCTION: TrLinkPeerNode 834118611Snjl * 835118611Snjl * PARAMETERS: Op1 - First peer 836118611Snjl * Op2 - Second peer 837118611Snjl * 838118611Snjl * RETURN: Op1 or the non-null node. 839118611Snjl * 840239340Sjkim * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 841118611Snjl * 842118611Snjl ******************************************************************************/ 843118611Snjl 844118611SnjlACPI_PARSE_OBJECT * 845118611SnjlTrLinkPeerNode ( 846118611Snjl ACPI_PARSE_OBJECT *Op1, 847118611Snjl ACPI_PARSE_OBJECT *Op2) 848118611Snjl{ 849118611Snjl ACPI_PARSE_OBJECT *Next; 850118611Snjl 851118611Snjl 852118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 853118611Snjl "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n", 854118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 855118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 856118611Snjl 857118611Snjl 858118611Snjl if ((!Op1) && (!Op2)) 859118611Snjl { 860118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 861241973Sjkim return (Op1); 862118611Snjl } 863118611Snjl 864118611Snjl /* If one of the nodes is null, just return the non-null node */ 865118611Snjl 866118611Snjl if (!Op2) 867118611Snjl { 868241973Sjkim return (Op1); 869118611Snjl } 870118611Snjl 871118611Snjl if (!Op1) 872118611Snjl { 873241973Sjkim return (Op2); 874118611Snjl } 875118611Snjl 876118611Snjl if (Op1 == Op2) 877118611Snjl { 878118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 879151937Sjkim "\n\n************* Internal error, linking node to itself %p\n\n\n", 880151937Sjkim Op1); 881151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 882151937Sjkim "Linking node to itself"); 883241973Sjkim return (Op1); 884118611Snjl } 885118611Snjl 886118611Snjl Op1->Asl.Parent = Op2->Asl.Parent; 887118611Snjl 888118611Snjl /* 889118611Snjl * Op 1 may already have a peer list (such as an IF/ELSE pair), 890118611Snjl * so we must walk to the end of the list and attach the new 891118611Snjl * peer at the end 892118611Snjl */ 893118611Snjl Next = Op1; 894118611Snjl while (Next->Asl.Next) 895118611Snjl { 896118611Snjl Next = Next->Asl.Next; 897118611Snjl } 898118611Snjl 899118611Snjl Next->Asl.Next = Op2; 900241973Sjkim return (Op1); 901118611Snjl} 902118611Snjl 903118611Snjl 904118611Snjl/******************************************************************************* 905118611Snjl * 906118611Snjl * FUNCTION: TrLinkPeerNodes 907118611Snjl * 908118611Snjl * PARAMETERS: NumPeers - The number of nodes in the list to follow 909118611Snjl * ... - A list of nodes to link together as peers 910118611Snjl * 911118611Snjl * RETURN: The first node in the list (head of the peer list) 912118611Snjl * 913118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes. 914118611Snjl * 915118611Snjl ******************************************************************************/ 916118611Snjl 917118611SnjlACPI_PARSE_OBJECT * 918118611SnjlTrLinkPeerNodes ( 919118611Snjl UINT32 NumPeers, 920118611Snjl ...) 921118611Snjl{ 922118611Snjl ACPI_PARSE_OBJECT *This; 923118611Snjl ACPI_PARSE_OBJECT *Next; 924118611Snjl va_list ap; 925118611Snjl UINT32 i; 926118611Snjl ACPI_PARSE_OBJECT *Start; 927118611Snjl 928118611Snjl 929118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 930209746Sjkim "\nLinkPeerNodes: (%u) ", NumPeers); 931118611Snjl 932118611Snjl va_start (ap, NumPeers); 933118611Snjl This = va_arg (ap, ACPI_PARSE_OBJECT *); 934118611Snjl Start = This; 935118611Snjl 936118611Snjl /* 937118611Snjl * Link all peers 938118611Snjl */ 939118611Snjl for (i = 0; i < (NumPeers -1); i++) 940118611Snjl { 941209746Sjkim DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 942118611Snjl 943118611Snjl while (This->Asl.Next) 944118611Snjl { 945118611Snjl This = This->Asl.Next; 946118611Snjl } 947118611Snjl 948118611Snjl /* Get another peer node */ 949118611Snjl 950118611Snjl Next = va_arg (ap, ACPI_PARSE_OBJECT *); 951118611Snjl if (!Next) 952118611Snjl { 953118611Snjl Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 954118611Snjl } 955118611Snjl 956118611Snjl /* link new node to the current node */ 957118611Snjl 958118611Snjl This->Asl.Next = Next; 959118611Snjl This = Next; 960118611Snjl } 961193529Sjkim va_end (ap); 962118611Snjl 963118611Snjl DbgPrint (ASL_PARSE_OUTPUT,"\n\n"); 964118611Snjl return (Start); 965118611Snjl} 966118611Snjl 967118611Snjl 968118611Snjl/******************************************************************************* 969118611Snjl * 970118611Snjl * FUNCTION: TrLinkChildNode 971118611Snjl * 972118611Snjl * PARAMETERS: Op1 - Parent node 973118611Snjl * Op2 - Op to become a child 974118611Snjl * 975118611Snjl * RETURN: The parent node 976118611Snjl * 977118611Snjl * DESCRIPTION: Link two nodes together as a parent and child 978118611Snjl * 979118611Snjl ******************************************************************************/ 980118611Snjl 981118611SnjlACPI_PARSE_OBJECT * 982118611SnjlTrLinkChildNode ( 983118611Snjl ACPI_PARSE_OBJECT *Op1, 984118611Snjl ACPI_PARSE_OBJECT *Op2) 985118611Snjl{ 986118611Snjl ACPI_PARSE_OBJECT *Next; 987118611Snjl 988118611Snjl 989118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 990118611Snjl "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n", 991118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 992118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 993118611Snjl 994118611Snjl if (!Op1 || !Op2) 995118611Snjl { 996241973Sjkim return (Op1); 997118611Snjl } 998118611Snjl 999118611Snjl Op1->Asl.Child = Op2; 1000118611Snjl 1001118611Snjl /* Set the child and all peers of the child to point to the parent */ 1002118611Snjl 1003118611Snjl Next = Op2; 1004118611Snjl while (Next) 1005118611Snjl { 1006118611Snjl Next->Asl.Parent = Op1; 1007118611Snjl Next = Next->Asl.Next; 1008118611Snjl } 1009118611Snjl 1010241973Sjkim return (Op1); 1011118611Snjl} 1012118611Snjl 1013118611Snjl 1014118611Snjl/******************************************************************************* 1015118611Snjl * 1016118611Snjl * FUNCTION: TrWalkParseTree 1017118611Snjl * 1018118611Snjl * PARAMETERS: Visitation - Type of walk 1019118611Snjl * DescendingCallback - Called during tree descent 1020118611Snjl * AscendingCallback - Called during tree ascent 1021118611Snjl * Context - To be passed to the callbacks 1022118611Snjl * 1023118611Snjl * RETURN: Status from callback(s) 1024118611Snjl * 1025118611Snjl * DESCRIPTION: Walk the entire parse tree. 1026118611Snjl * 1027118611Snjl ******************************************************************************/ 1028118611Snjl 1029118611SnjlACPI_STATUS 1030118611SnjlTrWalkParseTree ( 1031118611Snjl ACPI_PARSE_OBJECT *Op, 1032118611Snjl UINT32 Visitation, 1033118611Snjl ASL_WALK_CALLBACK DescendingCallback, 1034118611Snjl ASL_WALK_CALLBACK AscendingCallback, 1035118611Snjl void *Context) 1036118611Snjl{ 1037118611Snjl UINT32 Level; 1038118611Snjl BOOLEAN NodePreviouslyVisited; 1039118611Snjl ACPI_PARSE_OBJECT *StartOp = Op; 1040118611Snjl ACPI_STATUS Status; 1041118611Snjl 1042118611Snjl 1043118611Snjl if (!RootNode) 1044118611Snjl { 1045118611Snjl return (AE_OK); 1046118611Snjl } 1047118611Snjl 1048118611Snjl Level = 0; 1049118611Snjl NodePreviouslyVisited = FALSE; 1050118611Snjl 1051118611Snjl switch (Visitation) 1052118611Snjl { 1053118611Snjl case ASL_WALK_VISIT_DOWNWARD: 1054118611Snjl 1055118611Snjl while (Op) 1056118611Snjl { 1057118611Snjl if (!NodePreviouslyVisited) 1058118611Snjl { 1059151937Sjkim /* Let the callback process the node. */ 1060151937Sjkim 1061118611Snjl Status = DescendingCallback (Op, Level, Context); 1062118611Snjl if (ACPI_SUCCESS (Status)) 1063118611Snjl { 1064118611Snjl /* Visit children first, once */ 1065118611Snjl 1066118611Snjl if (Op->Asl.Child) 1067118611Snjl { 1068118611Snjl Level++; 1069118611Snjl Op = Op->Asl.Child; 1070118611Snjl continue; 1071118611Snjl } 1072118611Snjl } 1073118611Snjl else if (Status != AE_CTRL_DEPTH) 1074118611Snjl { 1075118611Snjl /* Exit immediately on any error */ 1076118611Snjl 1077118611Snjl return (Status); 1078118611Snjl } 1079118611Snjl } 1080118611Snjl 1081118611Snjl /* Terminate walk at start op */ 1082118611Snjl 1083118611Snjl if (Op == StartOp) 1084118611Snjl { 1085118611Snjl break; 1086118611Snjl } 1087118611Snjl 1088118611Snjl /* No more children, visit peers */ 1089118611Snjl 1090118611Snjl if (Op->Asl.Next) 1091118611Snjl { 1092118611Snjl Op = Op->Asl.Next; 1093118611Snjl NodePreviouslyVisited = FALSE; 1094118611Snjl } 1095118611Snjl else 1096118611Snjl { 1097118611Snjl /* No children or peers, re-visit parent */ 1098118611Snjl 1099118611Snjl if (Level != 0 ) 1100118611Snjl { 1101118611Snjl Level--; 1102118611Snjl } 1103118611Snjl Op = Op->Asl.Parent; 1104118611Snjl NodePreviouslyVisited = TRUE; 1105118611Snjl } 1106118611Snjl } 1107118611Snjl break; 1108118611Snjl 1109118611Snjl 1110118611Snjl case ASL_WALK_VISIT_UPWARD: 1111118611Snjl 1112118611Snjl while (Op) 1113118611Snjl { 1114118611Snjl /* Visit leaf node (no children) or parent node on return trip */ 1115118611Snjl 1116118611Snjl if ((!Op->Asl.Child) || 1117118611Snjl (NodePreviouslyVisited)) 1118118611Snjl { 1119151937Sjkim /* Let the callback process the node. */ 1120151937Sjkim 1121118611Snjl Status = AscendingCallback (Op, Level, Context); 1122118611Snjl if (ACPI_FAILURE (Status)) 1123118611Snjl { 1124118611Snjl return (Status); 1125118611Snjl } 1126118611Snjl } 1127118611Snjl else 1128118611Snjl { 1129118611Snjl /* Visit children first, once */ 1130118611Snjl 1131118611Snjl Level++; 1132118611Snjl Op = Op->Asl.Child; 1133118611Snjl continue; 1134118611Snjl } 1135118611Snjl 1136118611Snjl /* Terminate walk at start op */ 1137118611Snjl 1138118611Snjl if (Op == StartOp) 1139118611Snjl { 1140118611Snjl break; 1141118611Snjl } 1142118611Snjl 1143118611Snjl /* No more children, visit peers */ 1144118611Snjl 1145118611Snjl if (Op->Asl.Next) 1146118611Snjl { 1147118611Snjl Op = Op->Asl.Next; 1148118611Snjl NodePreviouslyVisited = FALSE; 1149118611Snjl } 1150118611Snjl else 1151118611Snjl { 1152118611Snjl /* No children or peers, re-visit parent */ 1153118611Snjl 1154118611Snjl if (Level != 0 ) 1155118611Snjl { 1156118611Snjl Level--; 1157118611Snjl } 1158118611Snjl Op = Op->Asl.Parent; 1159118611Snjl NodePreviouslyVisited = TRUE; 1160118611Snjl } 1161118611Snjl } 1162118611Snjl break; 1163118611Snjl 1164118611Snjl 1165118611Snjl case ASL_WALK_VISIT_TWICE: 1166118611Snjl 1167118611Snjl while (Op) 1168118611Snjl { 1169118611Snjl if (NodePreviouslyVisited) 1170118611Snjl { 1171118611Snjl Status = AscendingCallback (Op, Level, Context); 1172118611Snjl if (ACPI_FAILURE (Status)) 1173118611Snjl { 1174118611Snjl return (Status); 1175118611Snjl } 1176118611Snjl } 1177118611Snjl else 1178118611Snjl { 1179151937Sjkim /* Let the callback process the node. */ 1180151937Sjkim 1181118611Snjl Status = DescendingCallback (Op, Level, Context); 1182118611Snjl if (ACPI_SUCCESS (Status)) 1183118611Snjl { 1184118611Snjl /* Visit children first, once */ 1185118611Snjl 1186118611Snjl if (Op->Asl.Child) 1187118611Snjl { 1188118611Snjl Level++; 1189118611Snjl Op = Op->Asl.Child; 1190118611Snjl continue; 1191118611Snjl } 1192118611Snjl } 1193118611Snjl else if (Status != AE_CTRL_DEPTH) 1194118611Snjl { 1195118611Snjl /* Exit immediately on any error */ 1196118611Snjl 1197118611Snjl return (Status); 1198118611Snjl } 1199118611Snjl } 1200118611Snjl 1201118611Snjl /* Terminate walk at start op */ 1202118611Snjl 1203118611Snjl if (Op == StartOp) 1204118611Snjl { 1205118611Snjl break; 1206118611Snjl } 1207118611Snjl 1208118611Snjl /* No more children, visit peers */ 1209118611Snjl 1210118611Snjl if (Op->Asl.Next) 1211118611Snjl { 1212118611Snjl Op = Op->Asl.Next; 1213118611Snjl NodePreviouslyVisited = FALSE; 1214118611Snjl } 1215118611Snjl else 1216118611Snjl { 1217118611Snjl /* No children or peers, re-visit parent */ 1218118611Snjl 1219118611Snjl if (Level != 0 ) 1220118611Snjl { 1221118611Snjl Level--; 1222118611Snjl } 1223118611Snjl Op = Op->Asl.Parent; 1224118611Snjl NodePreviouslyVisited = TRUE; 1225118611Snjl } 1226118611Snjl } 1227118611Snjl break; 1228118611Snjl 1229118611Snjl default: 1230118611Snjl /* No other types supported */ 1231118611Snjl break; 1232118611Snjl } 1233118611Snjl 1234118611Snjl /* If we get here, the walk completed with no errors */ 1235118611Snjl 1236118611Snjl return (AE_OK); 1237118611Snjl} 1238