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