Subversion Repositories Kolibri OS

Rev

Rev 1498 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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