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