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