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