1 /******************************************************************************
   2  *
   3  * Module Name: asltree - parse tree management
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 }