1 /****************************************************************************** 2 * 3 * Module Name: asltree - parse tree management 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include <contrib/dev/acpica/compiler/aslcompiler.h> 153 #include "aslcompiler.y.h" 154 #include <contrib/dev/acpica/include/acapps.h> 155 #include <contrib/dev/acpica/include/acconvert.h> 156 #include <time.h> 157 158 #define _COMPONENT ACPI_COMPILER 159 ACPI_MODULE_NAME ("asltree") 160 161 /* Local prototypes */ 162 163 static ACPI_PARSE_OBJECT * 164 TrGetNextNode ( 165 void); 166 167 168 /******************************************************************************* 169 * 170 * FUNCTION: TrSetParent 171 * 172 * PARAMETERS: Op - To be set to new parent 173 * ParentOp - The parent 174 * 175 * RETURN: None, sets Op parent directly 176 * 177 * DESCRIPTION: Change the parent of a parse op. 178 * 179 ******************************************************************************/ 180 181 void 182 TrSetParent ( 183 ACPI_PARSE_OBJECT *Op, 184 ACPI_PARSE_OBJECT *ParentOp) 185 { 186 187 Op->Asl.Parent = ParentOp; 188 } 189 190 191 /******************************************************************************* 192 * 193 * FUNCTION: TrGetNextNode 194 * 195 * PARAMETERS: None 196 * 197 * RETURN: New parse node. Aborts on allocation failure 198 * 199 * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 200 * dynamic memory manager for performance reasons (This has a 201 * major impact on the speed of the compiler.) 202 * 203 ******************************************************************************/ 204 205 static ACPI_PARSE_OBJECT * 206 TrGetNextNode ( 207 void) 208 { 209 ASL_CACHE_INFO *Cache; 210 211 212 if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast) 213 { 214 /* Allocate a new buffer */ 215 216 Cache = UtLocalCalloc (sizeof (Cache->Next) + 217 (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE)); 218 219 /* Link new cache buffer to head of list */ 220 221 Cache->Next = Gbl_ParseOpCacheList; 222 Gbl_ParseOpCacheList = Cache; 223 224 /* Setup cache management pointers */ 225 226 Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer); 227 Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE; 228 } 229 230 Gbl_ParseOpCount++; 231 return (Gbl_ParseOpCacheNext++); 232 } 233 234 235 /******************************************************************************* 236 * 237 * FUNCTION: TrAllocateNode 238 * 239 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 240 * 241 * RETURN: New parse node. Aborts on allocation failure 242 * 243 * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 244 * 245 ******************************************************************************/ 246 247 ACPI_PARSE_OBJECT * 248 TrAllocateNode ( 249 UINT32 ParseOpcode) 250 { 251 ACPI_PARSE_OBJECT *Op; 252 ACPI_PARSE_OBJECT *LatestNode; 253 254 255 Op = TrGetNextNode (); 256 257 Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 258 Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 259 Op->Asl.LineNumber = Gbl_CurrentLineNumber; 260 Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 261 Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 262 Op->Asl.Column = Gbl_CurrentColumn; 263 264 UtSetParseOpName (Op); 265 266 /* The following is for capturing comments */ 267 268 if(Gbl_CaptureComments) 269 { 270 LatestNode = Gbl_CommentState.Latest_Parse_Node; 271 Op->Asl.InlineComment = NULL; 272 Op->Asl.EndNodeComment = NULL; 273 Op->Asl.CommentList = NULL; 274 Op->Asl.FileChanged = FALSE; 275 276 /* 277 * Check to see if the file name has changed before resetting the 278 * latest parse node. 279 */ 280 if (LatestNode && 281 (ParseOpcode != PARSEOP_INCLUDE) && 282 (ParseOpcode != PARSEOP_INCLUDE_END) && 283 strcmp (LatestNode->Asl.Filename, Op->Asl.Filename)) 284 { 285 CvDbgPrint ("latest node: %s\n", LatestNode->Asl.ParseOpName); 286 Op->Asl.FileChanged = TRUE; 287 if (Gbl_IncludeFileStack) 288 { 289 Op->Asl.ParentFilename = Gbl_IncludeFileStack->Filename; 290 } 291 else 292 { 293 Op->Asl.ParentFilename = NULL; 294 } 295 } 296 297 Gbl_CommentState.Latest_Parse_Node = Op; 298 CvDbgPrint ("trallocatenode=Set latest parse node to this node.\n"); 299 CvDbgPrint (" Op->Asl.ParseOpName = %s\n", 300 Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName); 301 CvDbgPrint (" Op->Asl.ParseOpcode = 0x%x\n", ParseOpcode); 302 303 if (Op->Asl.FileChanged) 304 { 305 CvDbgPrint(" file has been changed!\n"); 306 } 307 308 /* 309 * if this parse op's syntax uses () and {} (i.e. Package(1){0x00}) then 310 * set a flag in the comment state. This facilitates paring comments for 311 * these types of opcodes. 312 */ 313 if ((CvParseOpBlockType(Op) == (BLOCK_PAREN | BLOCK_BRACE)) && 314 (ParseOpcode != PARSEOP_DEFINITION_BLOCK)) 315 { 316 CvDbgPrint ("Parsing paren/Brace node now!\n"); 317 Gbl_CommentState.ParsingParenBraceNode = Op; 318 } 319 320 if (Gbl_Comment_List_Head) 321 { 322 CvDbgPrint ("Transferring...\n"); 323 Op->Asl.CommentList = Gbl_Comment_List_Head; 324 Gbl_Comment_List_Head = NULL; 325 Gbl_Comment_List_Tail = NULL; 326 CvDbgPrint (" Transferred current comment list to this node.\n"); 327 CvDbgPrint (" %s\n", Op->Asl.CommentList->Comment); 328 } 329 if (Gbl_Inline_Comment_Buffer) 330 { 331 Op->Asl.InlineComment = Gbl_Inline_Comment_Buffer; 332 Gbl_Inline_Comment_Buffer = NULL; 333 CvDbgPrint ("Transferred current inline comment list to this node.\n"); 334 } 335 336 } 337 338 return (Op); 339 } 340 341 342 /******************************************************************************* 343 * 344 * FUNCTION: TrReleaseNode 345 * 346 * PARAMETERS: Op - Op to be released 347 * 348 * RETURN: None 349 * 350 * DESCRIPTION: "release" a node. In truth, nothing is done since the node 351 * is part of a larger buffer 352 * 353 ******************************************************************************/ 354 355 void 356 TrReleaseNode ( 357 ACPI_PARSE_OBJECT *Op) 358 { 359 360 return; 361 } 362 363 364 /******************************************************************************* 365 * 366 * FUNCTION: TrSetCurrentFilename 367 * 368 * PARAMETERS: Op - An existing parse node 369 * 370 * RETURN: None 371 * 372 * DESCRIPTION: Save the include file filename. Used for debug output only. 373 * 374 ******************************************************************************/ 375 376 void 377 TrSetCurrentFilename ( 378 ACPI_PARSE_OBJECT *Op) 379 { 380 Op->Asl.Filename = Gbl_PreviousIncludeFilename; 381 } 382 383 384 /******************************************************************************* 385 * 386 * FUNCTION: TrUpdateNode 387 * 388 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 389 * Op - An existing parse node 390 * 391 * RETURN: The updated node 392 * 393 * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 394 * change an opcode to DEFAULT_ARG so that the node is ignored 395 * during the code generation. Also used to set generic integers 396 * to a specific size (8, 16, 32, or 64 bits) 397 * 398 ******************************************************************************/ 399 400 ACPI_PARSE_OBJECT * 401 TrUpdateNode ( 402 UINT32 ParseOpcode, 403 ACPI_PARSE_OBJECT *Op) 404 { 405 406 if (!Op) 407 { 408 return (NULL); 409 } 410 411 DbgPrint (ASL_PARSE_OUTPUT, 412 "\nUpdateNode: Old - %s, New - %s\n", 413 UtGetOpName (Op->Asl.ParseOpcode), 414 UtGetOpName (ParseOpcode)); 415 416 /* Assign new opcode and name */ 417 418 if (Op->Asl.ParseOpcode == PARSEOP_ONES) 419 { 420 switch (ParseOpcode) 421 { 422 case PARSEOP_BYTECONST: 423 424 Op->Asl.Value.Integer = ACPI_UINT8_MAX; 425 break; 426 427 case PARSEOP_WORDCONST: 428 429 Op->Asl.Value.Integer = ACPI_UINT16_MAX; 430 break; 431 432 case PARSEOP_DWORDCONST: 433 434 Op->Asl.Value.Integer = ACPI_UINT32_MAX; 435 break; 436 437 /* Don't need to do the QWORD case */ 438 439 default: 440 441 /* Don't care about others */ 442 break; 443 } 444 } 445 446 Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 447 UtSetParseOpName (Op); 448 449 /* 450 * For the BYTE, WORD, and DWORD constants, make sure that the integer 451 * that was passed in will actually fit into the data type 452 */ 453 switch (ParseOpcode) 454 { 455 case PARSEOP_BYTECONST: 456 457 UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 458 Op->Asl.Value.Integer &= ACPI_UINT8_MAX; 459 break; 460 461 case PARSEOP_WORDCONST: 462 463 UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 464 Op->Asl.Value.Integer &= ACPI_UINT16_MAX; 465 break; 466 467 case PARSEOP_DWORDCONST: 468 469 UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 470 Op->Asl.Value.Integer &= ACPI_UINT32_MAX; 471 break; 472 473 default: 474 475 /* Don't care about others, don't need to check QWORD */ 476 477 break; 478 } 479 480 /* Converter: if this is a method invocation, turn off capture comments. */ 481 if (Gbl_CaptureComments && 482 (ParseOpcode == PARSEOP_METHODCALL)) 483 { 484 Gbl_CommentState.CaptureComments = FALSE; 485 } 486 487 return (Op); 488 } 489 490 491 /******************************************************************************* 492 * 493 * FUNCTION: TrPrintNodeCompileFlags 494 * 495 * PARAMETERS: Flags - Flags word to be decoded 496 * 497 * RETURN: None 498 * 499 * DESCRIPTION: Decode a flags word to text. Displays all flags that are set. 500 * 501 ******************************************************************************/ 502 503 void 504 TrPrintNodeCompileFlags ( 505 UINT32 Flags) 506 { 507 UINT32 i; 508 UINT32 FlagBit = 1; 509 char *FlagName = NULL; 510 511 512 for (i = 0; i < 32; i++) 513 { 514 switch (Flags & FlagBit) 515 { 516 case NODE_VISITED: 517 518 FlagName = "NODE_VISITED"; 519 break; 520 521 case NODE_AML_PACKAGE: 522 523 FlagName = "NODE_AML_PACKAGE"; 524 break; 525 526 case NODE_IS_TARGET: 527 528 FlagName = "NODE_IS_TARGET"; 529 break; 530 531 case NODE_IS_RESOURCE_DESC: 532 533 FlagName = "NODE_IS_RESOURCE_DESC"; 534 break; 535 536 case NODE_IS_RESOURCE_FIELD: 537 538 FlagName = "NODE_IS_RESOURCE_FIELD"; 539 break; 540 541 case NODE_HAS_NO_EXIT: 542 543 FlagName = "NODE_HAS_NO_EXIT"; 544 break; 545 546 case NODE_IF_HAS_NO_EXIT: 547 548 FlagName = "NODE_IF_HAS_NO_EXIT"; 549 break; 550 551 case NODE_NAME_INTERNALIZED: 552 553 FlagName = "NODE_NAME_INTERNALIZED"; 554 break; 555 556 case NODE_METHOD_NO_RETVAL: 557 558 FlagName = "NODE_METHOD_NO_RETVAL"; 559 break; 560 561 case NODE_METHOD_SOME_NO_RETVAL: 562 563 FlagName = "NODE_METHOD_SOME_NO_RETVAL"; 564 break; 565 566 case NODE_RESULT_NOT_USED: 567 568 FlagName = "NODE_RESULT_NOT_USED"; 569 break; 570 571 case NODE_METHOD_TYPED: 572 573 FlagName = "NODE_METHOD_TYPED"; 574 break; 575 576 case NODE_COULD_NOT_REDUCE: 577 578 FlagName = "NODE_COULD_NOT_REDUCE"; 579 break; 580 581 case NODE_COMPILE_TIME_CONST: 582 583 FlagName = "NODE_COMPILE_TIME_CONST"; 584 break; 585 586 case NODE_IS_TERM_ARG: 587 588 FlagName = "NODE_IS_TERM_ARG"; 589 break; 590 591 case NODE_WAS_ONES_OP: 592 593 FlagName = "NODE_WAS_ONES_OP"; 594 break; 595 596 case NODE_IS_NAME_DECLARATION: 597 598 FlagName = "NODE_IS_NAME_DECLARATION"; 599 break; 600 601 case NODE_COMPILER_EMITTED: 602 603 FlagName = "NODE_COMPILER_EMITTED"; 604 break; 605 606 case NODE_IS_DUPLICATE: 607 608 FlagName = "NODE_IS_DUPLICATE"; 609 break; 610 611 case NODE_IS_RESOURCE_DATA: 612 613 FlagName = "NODE_IS_RESOURCE_DATA"; 614 break; 615 616 case NODE_IS_NULL_RETURN: 617 618 FlagName = "NODE_IS_NULL_RETURN"; 619 break; 620 621 default: 622 break; 623 } 624 625 if (FlagName) 626 { 627 DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName); 628 FlagName = NULL; 629 } 630 631 FlagBit <<= 1; 632 } 633 } 634 635 636 /******************************************************************************* 637 * 638 * FUNCTION: TrSetNodeFlags 639 * 640 * PARAMETERS: Op - An existing parse node 641 * Flags - New flags word 642 * 643 * RETURN: The updated parser op 644 * 645 * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 646 * 647 ******************************************************************************/ 648 649 ACPI_PARSE_OBJECT * 650 TrSetNodeFlags ( 651 ACPI_PARSE_OBJECT *Op, 652 UINT32 Flags) 653 { 654 655 if (!Op) 656 { 657 return (NULL); 658 } 659 660 DbgPrint (ASL_PARSE_OUTPUT, 661 "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags); 662 663 TrPrintNodeCompileFlags (Flags); 664 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 665 666 Op->Asl.CompileFlags |= Flags; 667 return (Op); 668 } 669 670 671 /******************************************************************************* 672 * 673 * FUNCTION: TrSetNodeAmlLength 674 * 675 * PARAMETERS: Op - An existing parse node 676 * Length - AML Length 677 * 678 * RETURN: The updated parser op 679 * 680 * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate 681 * the presence of a node that must be reduced to a fixed length 682 * constant. 683 * 684 ******************************************************************************/ 685 686 ACPI_PARSE_OBJECT * 687 TrSetNodeAmlLength ( 688 ACPI_PARSE_OBJECT *Op, 689 UINT32 Length) 690 { 691 692 DbgPrint (ASL_PARSE_OUTPUT, 693 "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length); 694 695 if (!Op) 696 { 697 return (NULL); 698 } 699 700 Op->Asl.AmlLength = Length; 701 return (Op); 702 } 703 704 705 /******************************************************************************* 706 * 707 * FUNCTION: TrSetEndLineNumber 708 * 709 * PARAMETERS: Op - An existing parse node 710 * 711 * RETURN: None. 712 * 713 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 714 * parse node to the current line numbers. 715 * 716 ******************************************************************************/ 717 718 void 719 TrSetEndLineNumber ( 720 ACPI_PARSE_OBJECT *Op) 721 { 722 723 /* If the end line # is already set, just return */ 724 725 if (Op->Asl.EndLine) 726 { 727 return; 728 } 729 730 Op->Asl.EndLine = Gbl_CurrentLineNumber; 731 Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 732 } 733 734 735 /******************************************************************************* 736 * 737 * FUNCTION: TrCreateAssignmentNode 738 * 739 * PARAMETERS: Target - Assignment target 740 * Source - Assignment source 741 * 742 * RETURN: Pointer to the new node. Aborts on allocation failure 743 * 744 * DESCRIPTION: Implements the C-style '=' operator. It changes the parse 745 * tree if possible to utilize the last argument of the math 746 * operators which is a target operand -- thus saving invocation 747 * of and additional Store() operator. An optimization. 748 * 749 ******************************************************************************/ 750 751 ACPI_PARSE_OBJECT * 752 TrCreateAssignmentNode ( 753 ACPI_PARSE_OBJECT *Target, 754 ACPI_PARSE_OBJECT *Source) 755 { 756 ACPI_PARSE_OBJECT *TargetOp; 757 ACPI_PARSE_OBJECT *SourceOp1; 758 ACPI_PARSE_OBJECT *SourceOp2; 759 ACPI_PARSE_OBJECT *Operator; 760 761 762 DbgPrint (ASL_PARSE_OUTPUT, 763 "\nTrCreateAssignmentNode Line [%u to %u] Source %s Target %s\n", 764 Source->Asl.LineNumber, Source->Asl.EndLine, 765 UtGetOpName (Source->Asl.ParseOpcode), 766 UtGetOpName (Target->Asl.ParseOpcode)); 767 768 TrSetNodeFlags (Target, NODE_IS_TARGET); 769 770 switch (Source->Asl.ParseOpcode) 771 { 772 /* 773 * Only these operators can be optimized because they have 774 * a target operand 775 */ 776 case PARSEOP_ADD: 777 case PARSEOP_AND: 778 case PARSEOP_DIVIDE: 779 case PARSEOP_INDEX: 780 case PARSEOP_MOD: 781 case PARSEOP_MULTIPLY: 782 case PARSEOP_NOT: 783 case PARSEOP_OR: 784 case PARSEOP_SHIFTLEFT: 785 case PARSEOP_SHIFTRIGHT: 786 case PARSEOP_SUBTRACT: 787 case PARSEOP_XOR: 788 789 break; 790 791 /* Otherwise, just create a normal Store operator */ 792 793 default: 794 795 goto CannotOptimize; 796 } 797 798 /* 799 * Transform the parse tree such that the target is moved to the 800 * last operand of the operator 801 */ 802 SourceOp1 = Source->Asl.Child; 803 SourceOp2 = SourceOp1->Asl.Next; 804 805 /* NOT only has one operand, but has a target */ 806 807 if (Source->Asl.ParseOpcode == PARSEOP_NOT) 808 { 809 SourceOp2 = SourceOp1; 810 } 811 812 /* DIVIDE has an extra target operand (remainder) */ 813 814 if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE) 815 { 816 SourceOp2 = SourceOp2->Asl.Next; 817 } 818 819 TargetOp = SourceOp2->Asl.Next; 820 821 /* 822 * Can't perform this optimization if there already is a target 823 * for the operator (ZERO is a "no target" placeholder). 824 */ 825 if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO) 826 { 827 goto CannotOptimize; 828 } 829 830 /* Link in the target as the final operand */ 831 832 SourceOp2->Asl.Next = Target; 833 Target->Asl.Parent = Source; 834 835 return (Source); 836 837 838 CannotOptimize: 839 840 Operator = TrAllocateNode (PARSEOP_STORE); 841 TrLinkChildren (Operator, 2, Source, Target); 842 843 /* Set the appropriate line numbers for the new node */ 844 845 Operator->Asl.LineNumber = Target->Asl.LineNumber; 846 Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber; 847 Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset; 848 Operator->Asl.Column = Target->Asl.Column; 849 850 return (Operator); 851 } 852 853 854 /******************************************************************************* 855 * 856 * FUNCTION: TrCreateLeafNode 857 * 858 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 859 * 860 * RETURN: Pointer to the new node. Aborts on allocation failure 861 * 862 * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 863 * assigned to the node) 864 * 865 ******************************************************************************/ 866 867 ACPI_PARSE_OBJECT * 868 TrCreateLeafNode ( 869 UINT32 ParseOpcode) 870 { 871 ACPI_PARSE_OBJECT *Op; 872 873 874 Op = TrAllocateNode (ParseOpcode); 875 876 DbgPrint (ASL_PARSE_OUTPUT, 877 "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 878 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode)); 879 880 return (Op); 881 } 882 883 884 /******************************************************************************* 885 * 886 * FUNCTION: TrCreateNullTarget 887 * 888 * PARAMETERS: None 889 * 890 * RETURN: Pointer to the new node. Aborts on allocation failure 891 * 892 * DESCRIPTION: Create a "null" target node. This is defined by the ACPI 893 * specification to be a zero AML opcode, and indicates that 894 * no target has been specified for the parent operation 895 * 896 ******************************************************************************/ 897 898 ACPI_PARSE_OBJECT * 899 TrCreateNullTarget ( 900 void) 901 { 902 ACPI_PARSE_OBJECT *Op; 903 904 905 Op = TrAllocateNode (PARSEOP_ZERO); 906 Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST); 907 908 DbgPrint (ASL_PARSE_OUTPUT, 909 "\nCreateNullTarget Ln/Col %u/%u NewNode %p Op %s\n", 910 Op->Asl.LineNumber, Op->Asl.Column, Op, 911 UtGetOpName (Op->Asl.ParseOpcode)); 912 913 return (Op); 914 } 915 916 917 /******************************************************************************* 918 * 919 * FUNCTION: TrCreateConstantLeafNode 920 * 921 * PARAMETERS: ParseOpcode - The constant opcode 922 * 923 * RETURN: Pointer to the new node. Aborts on allocation failure 924 * 925 * DESCRIPTION: Create a leaf node (no children or peers) for one of the 926 * special constants - __LINE__, __FILE__, and __DATE__. 927 * 928 * Note: An implemenation of __FUNC__ cannot happen here because we don't 929 * have a full parse tree at this time and cannot find the parent control 930 * method. If it is ever needed, __FUNC__ must be implemented later, after 931 * the parse tree has been fully constructed. 932 * 933 ******************************************************************************/ 934 935 ACPI_PARSE_OBJECT * 936 TrCreateConstantLeafNode ( 937 UINT32 ParseOpcode) 938 { 939 ACPI_PARSE_OBJECT *Op = NULL; 940 time_t CurrentTime; 941 char *StaticTimeString; 942 char *TimeString; 943 char *Filename; 944 945 946 switch (ParseOpcode) 947 { 948 case PARSEOP___LINE__: 949 950 Op = TrAllocateNode (PARSEOP_INTEGER); 951 Op->Asl.Value.Integer = Op->Asl.LineNumber; 952 break; 953 954 case PARSEOP___PATH__: 955 956 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 957 958 /* Op.Asl.Filename contains the full pathname to the file */ 959 960 Op->Asl.Value.String = Op->Asl.Filename; 961 break; 962 963 case PARSEOP___FILE__: 964 965 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 966 967 /* Get the simple filename from the full path */ 968 969 FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename); 970 Op->Asl.Value.String = Filename; 971 break; 972 973 case PARSEOP___DATE__: 974 975 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 976 977 /* Get a copy of the current time */ 978 979 CurrentTime = time (NULL); 980 StaticTimeString = ctime (&CurrentTime); 981 TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 982 strcpy (TimeString, StaticTimeString); 983 984 TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 985 Op->Asl.Value.String = TimeString; 986 break; 987 988 default: /* This would be an internal error */ 989 990 return (NULL); 991 } 992 993 DbgPrint (ASL_PARSE_OUTPUT, 994 "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p " 995 "Op %s Value %8.8X%8.8X \n", 996 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 997 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 998 return (Op); 999 } 1000 1001 1002 /******************************************************************************* 1003 * 1004 * FUNCTION: TrCreateTargetOperand 1005 * 1006 * PARAMETERS: OriginalOp - Op to be copied 1007 * 1008 * RETURN: Pointer to the new node. Aborts on allocation failure 1009 * 1010 * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style) 1011 * expressions where the target is the same as one of the 1012 * operands. A new node and subtree must be created from the 1013 * original so that the parse tree can be linked properly. 1014 * 1015 * NOTE: This code is specific to target operands that are the last 1016 * operand in an ASL/AML operator. Meaning that the top-level 1017 * parse Op in a possible subtree has a NULL Next pointer. 1018 * This simplifies the recursion. 1019 * 1020 * Subtree example: 1021 * DeRefOf (Local1) += 32 1022 * 1023 * This gets converted to: 1024 * Add (DeRefOf (Local1), 32, DeRefOf (Local1)) 1025 * 1026 * Each DeRefOf has a single child, Local1. Even more complex 1027 * subtrees can be created via the Index and DeRefOf operators. 1028 * 1029 ******************************************************************************/ 1030 1031 ACPI_PARSE_OBJECT * 1032 TrCreateTargetOperand ( 1033 ACPI_PARSE_OBJECT *OriginalOp, 1034 ACPI_PARSE_OBJECT *ParentOp) 1035 { 1036 ACPI_PARSE_OBJECT *Op; 1037 1038 1039 if (!OriginalOp) 1040 { 1041 return (NULL); 1042 } 1043 1044 Op = TrGetNextNode (); 1045 1046 /* Copy the pertinent values (omit link pointer fields) */ 1047 1048 Op->Asl.Value = OriginalOp->Asl.Value; 1049 Op->Asl.Filename = OriginalOp->Asl.Filename; 1050 Op->Asl.LineNumber = OriginalOp->Asl.LineNumber; 1051 Op->Asl.LogicalLineNumber = OriginalOp->Asl.LogicalLineNumber; 1052 Op->Asl.LogicalByteOffset = OriginalOp->Asl.LogicalByteOffset; 1053 Op->Asl.Column = OriginalOp->Asl.Column; 1054 Op->Asl.Flags = OriginalOp->Asl.Flags; 1055 Op->Asl.CompileFlags = OriginalOp->Asl.CompileFlags; 1056 Op->Asl.AmlOpcode = OriginalOp->Asl.AmlOpcode; 1057 Op->Asl.ParseOpcode = OriginalOp->Asl.ParseOpcode; 1058 Op->Asl.Parent = ParentOp; 1059 UtSetParseOpName (Op); 1060 1061 /* Copy a possible subtree below this node */ 1062 1063 if (OriginalOp->Asl.Child) 1064 { 1065 Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op); 1066 } 1067 1068 if (OriginalOp->Asl.Next) /* Null for top-level node */ 1069 { 1070 Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp); 1071 } 1072 1073 return (Op); 1074 } 1075 1076 1077 /******************************************************************************* 1078 * 1079 * FUNCTION: TrCreateValuedLeafNode 1080 * 1081 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 1082 * Value - Value to be assigned to the node 1083 * 1084 * RETURN: Pointer to the new node. Aborts on allocation failure 1085 * 1086 * DESCRIPTION: Create a leaf node (no children or peers) with a value 1087 * assigned to it 1088 * 1089 ******************************************************************************/ 1090 1091 ACPI_PARSE_OBJECT * 1092 TrCreateValuedLeafNode ( 1093 UINT32 ParseOpcode, 1094 UINT64 Value) 1095 { 1096 ACPI_PARSE_OBJECT *Op; 1097 1098 1099 Op = TrAllocateNode (ParseOpcode); 1100 1101 DbgPrint (ASL_PARSE_OUTPUT, 1102 "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p " 1103 "Op %s Value %8.8X%8.8X ", 1104 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 1105 ACPI_FORMAT_UINT64 (Value)); 1106 Op->Asl.Value.Integer = Value; 1107 1108 switch (ParseOpcode) 1109 { 1110 case PARSEOP_STRING_LITERAL: 1111 1112 DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 1113 break; 1114 1115 case PARSEOP_NAMESEG: 1116 1117 DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 1118 break; 1119 1120 case PARSEOP_NAMESTRING: 1121 1122 DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 1123 break; 1124 1125 case PARSEOP_EISAID: 1126 1127 DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 1128 break; 1129 1130 case PARSEOP_METHOD: 1131 1132 DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 1133 break; 1134 1135 case PARSEOP_INTEGER: 1136 1137 DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X", 1138 ACPI_FORMAT_UINT64 (Value)); 1139 break; 1140 1141 default: 1142 1143 break; 1144 } 1145 1146 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 1147 return (Op); 1148 } 1149 1150 1151 /******************************************************************************* 1152 * 1153 * FUNCTION: TrCreateNode 1154 * 1155 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 1156 * NumChildren - Number of children to follow 1157 * ... - A list of child nodes to link to the new 1158 * node. NumChildren long. 1159 * 1160 * RETURN: Pointer to the new node. Aborts on allocation failure 1161 * 1162 * DESCRIPTION: Create a new parse node and link together a list of child 1163 * nodes underneath the new node. 1164 * 1165 ******************************************************************************/ 1166 1167 ACPI_PARSE_OBJECT * 1168 TrCreateNode ( 1169 UINT32 ParseOpcode, 1170 UINT32 NumChildren, 1171 ...) 1172 { 1173 ACPI_PARSE_OBJECT *Op; 1174 ACPI_PARSE_OBJECT *Child; 1175 ACPI_PARSE_OBJECT *PrevChild; 1176 va_list ap; 1177 UINT32 i; 1178 BOOLEAN FirstChild; 1179 1180 1181 va_start (ap, NumChildren); 1182 1183 /* Allocate one new node */ 1184 1185 Op = TrAllocateNode (ParseOpcode); 1186 1187 DbgPrint (ASL_PARSE_OUTPUT, 1188 "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 1189 Op->Asl.LineNumber, Op->Asl.Column, Op, 1190 NumChildren, UtGetOpName(ParseOpcode)); 1191 1192 /* Some extra debug output based on the parse opcode */ 1193 1194 switch (ParseOpcode) 1195 { 1196 case PARSEOP_ASL_CODE: 1197 1198 Gbl_ParseTreeRoot = Op; 1199 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1200 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1201 break; 1202 1203 case PARSEOP_DEFINITION_BLOCK: 1204 1205 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1206 break; 1207 1208 case PARSEOP_OPERATIONREGION: 1209 1210 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1211 break; 1212 1213 case PARSEOP_OR: 1214 1215 DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1216 break; 1217 1218 default: 1219 1220 /* Nothing to do for other opcodes */ 1221 1222 break; 1223 } 1224 1225 /* Link the new node to its children */ 1226 1227 PrevChild = NULL; 1228 FirstChild = TRUE; 1229 for (i = 0; i < NumChildren; i++) 1230 { 1231 /* Get the next child */ 1232 1233 Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1234 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1235 1236 /* 1237 * If child is NULL, this means that an optional argument 1238 * was omitted. We must create a placeholder with a special 1239 * opcode (DEFAULT_ARG) so that the code generator will know 1240 * that it must emit the correct default for this argument 1241 */ 1242 if (!Child) 1243 { 1244 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1245 } 1246 1247 /* Link first child to parent */ 1248 1249 if (FirstChild) 1250 { 1251 FirstChild = FALSE; 1252 Op->Asl.Child = Child; 1253 1254 /* 1255 * For the ASL-/ASL+ converter: if the ParseOp is a connection, 1256 * external, offset or accessAs, it means that the comments in the 1257 * FirstChild belongs to their parent due to the parsing order in 1258 * the .y files. To correct this, take the comments in the 1259 * FirstChild place it in the parent. This also means that 1260 * legitimate comments for the child gets put to the parent. 1261 */ 1262 if (Gbl_CaptureComments && 1263 ((ParseOpcode == PARSEOP_CONNECTION) || 1264 (ParseOpcode == PARSEOP_EXTERNAL) || 1265 (ParseOpcode == PARSEOP_OFFSET) || 1266 (ParseOpcode == PARSEOP_ACCESSAS))) 1267 { 1268 Op->Asl.CommentList = Child->Asl.CommentList; 1269 Op->Asl.EndBlkComment = Child->Asl.EndBlkComment; 1270 Op->Asl.InlineComment = Child->Asl.InlineComment; 1271 Op->Asl.FileChanged = Child->Asl.FileChanged; 1272 1273 Child->Asl.CommentList = NULL; 1274 Child->Asl.EndBlkComment = NULL; 1275 Child->Asl.InlineComment = NULL; 1276 Child->Asl.FileChanged = FALSE; 1277 1278 /* 1279 * These do not need to be "passed off". They can be copied 1280 * because the code for these opcodes should be printed in the 1281 * same file. 1282 */ 1283 Op->Asl.Filename = Child->Asl.Filename; 1284 Op->Asl.ParentFilename = Child->Asl.ParentFilename; 1285 } 1286 } 1287 1288 /* Point all children to parent */ 1289 1290 Child->Asl.Parent = Op; 1291 1292 /* Link children in a peer list */ 1293 1294 if (PrevChild) 1295 { 1296 PrevChild->Asl.Next = Child; 1297 }; 1298 1299 /* Get the comment from last child in the resource template call */ 1300 1301 if (Gbl_CaptureComments && 1302 (Op->Asl.ParseOpcode == PARSEOP_RESOURCETEMPLATE)) 1303 { 1304 CvDbgPrint ("Transferred current comment list to this node.\n"); 1305 Op->Asl.CommentList = Child->Asl.CommentList; 1306 Child->Asl.CommentList = NULL; 1307 Op->Asl.InlineComment = Child->Asl.InlineComment; 1308 Child->Asl.InlineComment = NULL; 1309 } 1310 1311 /* 1312 * This child might be a list, point all nodes in the list 1313 * to the same parent 1314 */ 1315 while (Child->Asl.Next) 1316 { 1317 Child = Child->Asl.Next; 1318 Child->Asl.Parent = Op; 1319 } 1320 1321 PrevChild = Child; 1322 } 1323 va_end(ap); 1324 1325 DbgPrint (ASL_PARSE_OUTPUT, "\n"); 1326 return (Op); 1327 } 1328 1329 1330 /******************************************************************************* 1331 * 1332 * FUNCTION: TrLinkChildren 1333 * 1334 * PARAMETERS: Op - An existing parse node 1335 * NumChildren - Number of children to follow 1336 * ... - A list of child nodes to link to the new 1337 * node. NumChildren long. 1338 * 1339 * RETURN: The updated (linked) node 1340 * 1341 * DESCRIPTION: Link a group of nodes to an existing parse node 1342 * 1343 ******************************************************************************/ 1344 1345 ACPI_PARSE_OBJECT * 1346 TrLinkChildren ( 1347 ACPI_PARSE_OBJECT *Op, 1348 UINT32 NumChildren, 1349 ...) 1350 { 1351 ACPI_PARSE_OBJECT *Child; 1352 ACPI_PARSE_OBJECT *PrevChild; 1353 va_list ap; 1354 UINT32 i; 1355 BOOLEAN FirstChild; 1356 1357 1358 va_start (ap, NumChildren); 1359 1360 1361 TrSetEndLineNumber (Op); 1362 1363 DbgPrint (ASL_PARSE_OUTPUT, 1364 "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 1365 Op->Asl.LineNumber, Op->Asl.EndLine, 1366 Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 1367 1368 switch (Op->Asl.ParseOpcode) 1369 { 1370 case PARSEOP_ASL_CODE: 1371 1372 Gbl_ParseTreeRoot = Op; 1373 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1374 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1375 break; 1376 1377 case PARSEOP_DEFINITION_BLOCK: 1378 1379 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1380 break; 1381 1382 case PARSEOP_OPERATIONREGION: 1383 1384 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1385 break; 1386 1387 case PARSEOP_OR: 1388 1389 DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1390 break; 1391 1392 default: 1393 1394 /* Nothing to do for other opcodes */ 1395 1396 break; 1397 } 1398 1399 /* The following is for capturing comments */ 1400 1401 if(Gbl_CaptureComments) 1402 { 1403 /* 1404 * If there are "regular comments" detected at this point, 1405 * then is an endBlk comment. Categorize it as so and distribute 1406 * all regular comments to this parse node. 1407 */ 1408 if (Gbl_Comment_List_Head) 1409 { 1410 Op->Asl.EndBlkComment = Gbl_Comment_List_Head; 1411 CvDbgPrint ("EndBlk Comment for %s: %s", 1412 Op->Asl.ParseOpName, Gbl_Comment_List_Head->Comment); 1413 Gbl_Comment_List_Head = NULL; 1414 Gbl_Comment_List_Tail = NULL; 1415 } 1416 } 1417 1418 /* Link the new node to it's children */ 1419 1420 PrevChild = NULL; 1421 FirstChild = TRUE; 1422 for (i = 0; i < NumChildren; i++) 1423 { 1424 Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1425 1426 if ((Child == PrevChild) && (Child != NULL)) 1427 { 1428 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 1429 "Child node list invalid"); 1430 va_end(ap); 1431 return (Op); 1432 } 1433 1434 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1435 1436 /* 1437 * If child is NULL, this means that an optional argument 1438 * was omitted. We must create a placeholder with a special 1439 * opcode (DEFAULT_ARG) so that the code generator will know 1440 * that it must emit the correct default for this argument 1441 */ 1442 if (!Child) 1443 { 1444 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1445 } 1446 1447 /* Link first child to parent */ 1448 1449 if (FirstChild) 1450 { 1451 FirstChild = FALSE; 1452 Op->Asl.Child = Child; 1453 } 1454 1455 /* Point all children to parent */ 1456 1457 Child->Asl.Parent = Op; 1458 1459 /* Link children in a peer list */ 1460 1461 if (PrevChild) 1462 { 1463 PrevChild->Asl.Next = Child; 1464 }; 1465 1466 /* 1467 * This child might be a list, point all nodes in the list 1468 * to the same parent 1469 */ 1470 while (Child->Asl.Next) 1471 { 1472 Child = Child->Asl.Next; 1473 Child->Asl.Parent = Op; 1474 } 1475 1476 PrevChild = Child; 1477 } 1478 1479 va_end(ap); 1480 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 1481 1482 1483 if(Gbl_CaptureComments) 1484 { 1485 Gbl_CommentState.Latest_Parse_Node = Op; 1486 CvDbgPrint ("trlinkchildren=====Set latest parse node to this node.\n"); 1487 } 1488 return (Op); 1489 } 1490 1491 1492 /******************************************************************************* 1493 * 1494 * FUNCTION: TrLinkPeerNode 1495 * 1496 * PARAMETERS: Op1 - First peer 1497 * Op2 - Second peer 1498 * 1499 * RETURN: Op1 or the non-null node. 1500 * 1501 * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 1502 * 1503 ******************************************************************************/ 1504 1505 ACPI_PARSE_OBJECT * 1506 TrLinkPeerNode ( 1507 ACPI_PARSE_OBJECT *Op1, 1508 ACPI_PARSE_OBJECT *Op2) 1509 { 1510 ACPI_PARSE_OBJECT *Next; 1511 1512 1513 DbgPrint (ASL_PARSE_OUTPUT, 1514 "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n", 1515 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 1516 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 1517 1518 1519 if ((!Op1) && (!Op2)) 1520 { 1521 DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 1522 return (Op1); 1523 } 1524 1525 /* If one of the nodes is null, just return the non-null node */ 1526 1527 if (!Op2) 1528 { 1529 return (Op1); 1530 } 1531 1532 if (!Op1) 1533 { 1534 return (Op2); 1535 } 1536 1537 if (Op1 == Op2) 1538 { 1539 DbgPrint (ASL_DEBUG_OUTPUT, 1540 "\n************* Internal error, linking node to itself %p\n", 1541 Op1); 1542 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 1543 "Linking node to itself"); 1544 return (Op1); 1545 } 1546 1547 Op1->Asl.Parent = Op2->Asl.Parent; 1548 1549 /* 1550 * Op 1 may already have a peer list (such as an IF/ELSE pair), 1551 * so we must walk to the end of the list and attach the new 1552 * peer at the end 1553 */ 1554 Next = Op1; 1555 while (Next->Asl.Next) 1556 { 1557 Next = Next->Asl.Next; 1558 } 1559 1560 Next->Asl.Next = Op2; 1561 return (Op1); 1562 } 1563 1564 1565 /******************************************************************************* 1566 * 1567 * FUNCTION: TrLinkPeerNodes 1568 * 1569 * PARAMETERS: NumPeers - The number of nodes in the list to follow 1570 * ... - A list of nodes to link together as peers 1571 * 1572 * RETURN: The first node in the list (head of the peer list) 1573 * 1574 * DESCRIPTION: Link together an arbitrary number of peer nodes. 1575 * 1576 ******************************************************************************/ 1577 1578 ACPI_PARSE_OBJECT * 1579 TrLinkPeerNodes ( 1580 UINT32 NumPeers, 1581 ...) 1582 { 1583 ACPI_PARSE_OBJECT *This; 1584 ACPI_PARSE_OBJECT *Next; 1585 va_list ap; 1586 UINT32 i; 1587 ACPI_PARSE_OBJECT *Start; 1588 1589 1590 DbgPrint (ASL_PARSE_OUTPUT, 1591 "\nLinkPeerNodes: (%u) ", NumPeers); 1592 1593 va_start (ap, NumPeers); 1594 This = va_arg (ap, ACPI_PARSE_OBJECT *); 1595 Start = This; 1596 1597 /* 1598 * Link all peers 1599 */ 1600 for (i = 0; i < (NumPeers -1); i++) 1601 { 1602 DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 1603 1604 while (This->Asl.Next) 1605 { 1606 This = This->Asl.Next; 1607 } 1608 1609 /* Get another peer node */ 1610 1611 Next = va_arg (ap, ACPI_PARSE_OBJECT *); 1612 if (!Next) 1613 { 1614 Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1615 } 1616 1617 /* link new node to the current node */ 1618 1619 This->Asl.Next = Next; 1620 This = Next; 1621 } 1622 va_end (ap); 1623 1624 DbgPrint (ASL_PARSE_OUTPUT,"\n"); 1625 return (Start); 1626 } 1627 1628 1629 /******************************************************************************* 1630 * 1631 * FUNCTION: TrLinkChildNode 1632 * 1633 * PARAMETERS: Op1 - Parent node 1634 * Op2 - Op to become a child 1635 * 1636 * RETURN: The parent node 1637 * 1638 * DESCRIPTION: Link two nodes together as a parent and child 1639 * 1640 ******************************************************************************/ 1641 1642 ACPI_PARSE_OBJECT * 1643 TrLinkChildNode ( 1644 ACPI_PARSE_OBJECT *Op1, 1645 ACPI_PARSE_OBJECT *Op2) 1646 { 1647 ACPI_PARSE_OBJECT *Next; 1648 1649 1650 DbgPrint (ASL_PARSE_OUTPUT, 1651 "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n", 1652 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 1653 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 1654 1655 /* 1656 * Converter: if TrLinkChildNode is called to link a method call, 1657 * turn on capture comments as it signifies that we are done parsing 1658 * a method call. 1659 */ 1660 if (Gbl_CaptureComments) 1661 { 1662 if (Op1->Asl.ParseOpcode == PARSEOP_METHODCALL) 1663 { 1664 Gbl_CommentState.CaptureComments = TRUE; 1665 } 1666 Gbl_CommentState.Latest_Parse_Node = Op1; 1667 } 1668 if (!Op1 || !Op2) 1669 { 1670 return (Op1); 1671 } 1672 1673 Op1->Asl.Child = Op2; 1674 1675 /* Set the child and all peers of the child to point to the parent */ 1676 1677 Next = Op2; 1678 while (Next) 1679 { 1680 Next->Asl.Parent = Op1; 1681 Next = Next->Asl.Next; 1682 } 1683 1684 return (Op1); 1685 } 1686 1687 1688 /******************************************************************************* 1689 * 1690 * FUNCTION: TrWalkParseTree 1691 * 1692 * PARAMETERS: Visitation - Type of walk 1693 * DescendingCallback - Called during tree descent 1694 * AscendingCallback - Called during tree ascent 1695 * Context - To be passed to the callbacks 1696 * 1697 * RETURN: Status from callback(s) 1698 * 1699 * DESCRIPTION: Walk the entire parse tree. 1700 * 1701 ******************************************************************************/ 1702 1703 ACPI_STATUS 1704 TrWalkParseTree ( 1705 ACPI_PARSE_OBJECT *Op, 1706 UINT32 Visitation, 1707 ASL_WALK_CALLBACK DescendingCallback, 1708 ASL_WALK_CALLBACK AscendingCallback, 1709 void *Context) 1710 { 1711 UINT32 Level; 1712 BOOLEAN NodePreviouslyVisited; 1713 ACPI_PARSE_OBJECT *StartOp = Op; 1714 ACPI_STATUS Status; 1715 1716 1717 if (!Gbl_ParseTreeRoot) 1718 { 1719 return (AE_OK); 1720 } 1721 1722 Level = 0; 1723 NodePreviouslyVisited = FALSE; 1724 1725 switch (Visitation) 1726 { 1727 case ASL_WALK_VISIT_DOWNWARD: 1728 1729 while (Op) 1730 { 1731 if (!NodePreviouslyVisited) 1732 { 1733 /* Let the callback process the node. */ 1734 1735 Status = DescendingCallback (Op, Level, Context); 1736 if (ACPI_SUCCESS (Status)) 1737 { 1738 /* Visit children first, once */ 1739 1740 if (Op->Asl.Child) 1741 { 1742 Level++; 1743 Op = Op->Asl.Child; 1744 continue; 1745 } 1746 } 1747 else if (Status != AE_CTRL_DEPTH) 1748 { 1749 /* Exit immediately on any error */ 1750 1751 return (Status); 1752 } 1753 } 1754 1755 /* Terminate walk at start op */ 1756 1757 if (Op == StartOp) 1758 { 1759 break; 1760 } 1761 1762 /* No more children, visit peers */ 1763 1764 if (Op->Asl.Next) 1765 { 1766 Op = Op->Asl.Next; 1767 NodePreviouslyVisited = FALSE; 1768 } 1769 else 1770 { 1771 /* No children or peers, re-visit parent */ 1772 1773 if (Level != 0 ) 1774 { 1775 Level--; 1776 } 1777 Op = Op->Asl.Parent; 1778 NodePreviouslyVisited = TRUE; 1779 } 1780 } 1781 break; 1782 1783 case ASL_WALK_VISIT_UPWARD: 1784 1785 while (Op) 1786 { 1787 /* Visit leaf node (no children) or parent node on return trip */ 1788 1789 if ((!Op->Asl.Child) || 1790 (NodePreviouslyVisited)) 1791 { 1792 /* Let the callback process the node. */ 1793 1794 Status = AscendingCallback (Op, Level, Context); 1795 if (ACPI_FAILURE (Status)) 1796 { 1797 return (Status); 1798 } 1799 } 1800 else 1801 { 1802 /* Visit children first, once */ 1803 1804 Level++; 1805 Op = Op->Asl.Child; 1806 continue; 1807 } 1808 1809 /* Terminate walk at start op */ 1810 1811 if (Op == StartOp) 1812 { 1813 break; 1814 } 1815 1816 /* No more children, visit peers */ 1817 1818 if (Op->Asl.Next) 1819 { 1820 Op = Op->Asl.Next; 1821 NodePreviouslyVisited = FALSE; 1822 } 1823 else 1824 { 1825 /* No children or peers, re-visit parent */ 1826 1827 if (Level != 0 ) 1828 { 1829 Level--; 1830 } 1831 Op = Op->Asl.Parent; 1832 NodePreviouslyVisited = TRUE; 1833 } 1834 } 1835 break; 1836 1837 case ASL_WALK_VISIT_TWICE: 1838 1839 while (Op) 1840 { 1841 if (NodePreviouslyVisited) 1842 { 1843 Status = AscendingCallback (Op, Level, Context); 1844 if (ACPI_FAILURE (Status)) 1845 { 1846 return (Status); 1847 } 1848 } 1849 else 1850 { 1851 /* Let the callback process the node. */ 1852 1853 Status = DescendingCallback (Op, Level, Context); 1854 if (ACPI_SUCCESS (Status)) 1855 { 1856 /* Visit children first, once */ 1857 1858 if (Op->Asl.Child) 1859 { 1860 Level++; 1861 Op = Op->Asl.Child; 1862 continue; 1863 } 1864 } 1865 else if (Status != AE_CTRL_DEPTH) 1866 { 1867 /* Exit immediately on any error */ 1868 1869 return (Status); 1870 } 1871 } 1872 1873 /* Terminate walk at start op */ 1874 1875 if (Op == StartOp) 1876 { 1877 break; 1878 } 1879 1880 /* No more children, visit peers */ 1881 1882 if (Op->Asl.Next) 1883 { 1884 Op = Op->Asl.Next; 1885 NodePreviouslyVisited = FALSE; 1886 } 1887 else 1888 { 1889 /* No children or peers, re-visit parent */ 1890 1891 if (Level != 0 ) 1892 { 1893 Level--; 1894 } 1895 Op = Op->Asl.Parent; 1896 NodePreviouslyVisited = TRUE; 1897 } 1898 } 1899 break; 1900 1901 default: 1902 /* No other types supported */ 1903 break; 1904 } 1905 1906 /* If we get here, the walk completed with no errors */ 1907 1908 return (AE_OK); 1909 } 1910